Energyflow UI: expandable consumers (ext, aux) (#24316)

This commit is contained in:
Michael Geers 2025-10-10 21:33:52 +02:00 • committed by GitHub
parent 18aac6b0ab
commit 4bd04f9e56
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 62 additions and 25 deletions

View file

@ -264,7 +264,7 @@ import formatter, { POWER_UNIT } from "@/mixins/formatter";
import collector from "@/mixins/collector.js";
import api from "@/api";
import { defineComponent, type PropType } from "vue";
import type { Battery, SelectOption, CURRENCY, Forecast } from "@/types/evcc";
import type { BatteryMeter, SelectOption, CURRENCY, Forecast } from "@/types/evcc";
import { SMART_COST_TYPE } from "@/types/evcc";
export default defineComponent({
@ -277,7 +277,7 @@ export default defineComponent({
batterySoc: { type: Number, default: 0 },
bufferStartSoc: { type: Number, default: 0 },
batteryDischargeControl: Boolean,
battery: { type: Array as PropType<Battery[]>, default: () => [] },
battery: { type: Array as PropType<BatteryMeter[]>, default: () => [] },
batteryGridChargeLimit: { type: Number, default: null },
smartCostAvailable: Boolean,
smartCostType: String as PropType<SMART_COST_TYPE>,

View file

@ -94,7 +94,7 @@
@details-clicked="openForecastModal"
@toggle="togglePv"
>
<template v-if="multiplePv" #expanded>
<template v-if="pv.length > 1" #expanded>
<EnergyflowEntry
v-for="(p, index) in pv"
:key="index"
@ -127,7 +127,7 @@
<template v-if="batteryGridChargeLimitSet" #subline>
<div class="d-none d-md-block">&nbsp;</div>
</template>
<template v-if="multipleBattery" #expanded>
<template v-if="battery.length > 1" #expanded>
<EnergyflowEntry
v-for="(b, index) in battery"
:key="index"
@ -171,7 +171,21 @@
:detailsFmt="detailsFmt"
:detailsTooltip="detailsTooltip(tariffPriceHome, tariffCo2Home)"
data-testid="energyflow-entry-home"
/>
:expanded="consumersExpanded"
@toggle="toggleConsumers"
>
<template v-if="consumers.length > 0" #expanded>
<EnergyflowEntry
v-for="(c, index) in consumers"
:key="index"
:name="c.title || genericConsumerTitle(index)"
:power="c.power"
:powerUnit="powerUnit"
icon="vehicle"
:iconProps="{ names: [c.icon || 'generic'] }"
/>
</template>
</EnergyflowEntry>
<EnergyflowEntry
:name="loadpointsLabel"
icon="vehicle"
@ -248,7 +262,7 @@
</span>
</button>
</template>
<template v-if="multipleBattery" #expanded>
<template v-if="battery.length > 1" #expanded>
<EnergyflowEntry
v-for="(b, index) in battery"
:key="index"
@ -290,7 +304,8 @@ import collector from "@/mixins/collector.js";
import { defineComponent, type PropType } from "vue";
import {
SMART_COST_TYPE,
type Battery,
type BatteryMeter,
type Meter,
type CURRENCY,
type Forecast,
type UiLoadpoint,
@ -309,11 +324,13 @@ export default defineComponent({
gridPower: { type: Number, default: 0 },
homePower: { type: Number, default: 0 },
pvConfigured: Boolean,
pv: { type: Array as PropType<Pv[]> },
pv: { type: Array as PropType<Meter[]>, default: () => [] },
aux: { type: Array as PropType<Meter[]>, default: () => [] },
ext: { type: Array as PropType<Meter[]>, default: () => [] },
pvPower: { type: Number, default: 0 },
loadpoints: { type: Array as PropType<UiLoadpoint[]>, default: () => [] },
batteryConfigured: { type: Boolean },
battery: { type: Array as PropType<Battery[]> },
battery: { type: Array as PropType<BatteryMeter[]>, default: () => [] },
batteryPower: { type: Number, default: 0 },
batterySoc: { type: Number, default: 0 },
batteryDischargeControl: { type: Boolean },
@ -410,12 +427,6 @@ export default defineComponent({
batteryFmt() {
return (soc: number) => this.fmtPercentage(soc, 0);
},
multipleBattery() {
return (this.battery?.length || 0) > 1;
},
multiplePv() {
return (this.pv?.length || 0) > 1;
},
fmtLoadpointSoc() {
return (soc: number) => this.fmtPercentage(soc, 0);
},
@ -478,12 +489,18 @@ export default defineComponent({
loadpointsExpanded() {
return settings.energyflowLoadpoints;
},
consumersExpanded() {
return settings.energyflowConsumers;
},
loadpointsLabel() {
// @ts-expect-error plural
return this.$t("main.energyflow.loadpoints", this.activeLoadpointsCount, {
count: this.activeLoadpointsCount,
});
},
consumers() {
return [...this.aux, ...this.ext];
},
},
watch: {
pvConfigured() {
@ -582,12 +599,19 @@ export default defineComponent({
settings.energyflowLoadpoints = !settings.energyflowLoadpoints;
this.$nextTick(this.updateHeight);
},
toggleConsumers() {
settings.energyflowConsumers = !settings.energyflowConsumers;
this.$nextTick(this.updateHeight);
},
genericBatteryTitle(index: number) {
return `${this.$t("config.devices.batteryStorage")} #${index + 1}`;
},
genericPvTitle(index: number) {
return `${this.$t("config.devices.solarSystem")} #${index + 1}`;
},
genericConsumerTitle(index: number) {
return `${this.$t("config.devices.consumer")} #${index + 1}`;
},
},
});
</script>

View file

@ -1,4 +0,0 @@
interface Pv {
title?: string;
power: number;
}

View file

@ -87,7 +87,8 @@ import WelcomeIcons from "./WelcomeIcons.vue";
import { defineComponent, type PropType } from "vue";
import type {
AuthProviders,
Battery,
BatteryMeter,
Meter,
CURRENCY,
Forecast,
Notification,
@ -123,14 +124,16 @@ export default defineComponent({
grid: Object as PropType<Grid>,
homePower: Number,
pvPower: Number,
pv: { type: Array, default: () => [] },
pv: { type: Array as PropType<Meter[]>, default: () => [] },
aux: { type: Array as PropType<Meter[]>, default: () => [] },
ext: { type: Array as PropType<Meter[]>, default: () => [] },
batteryPower: Number,
batterySoc: Number,
batteryDischargeControl: Boolean,
batteryGridChargeLimit: { type: Number, default: null },
batteryGridChargeActive: Boolean,
batteryMode: String,
battery: { type: Array as PropType<Battery[]>, default: () => [] },
battery: { type: Array as PropType<BatteryMeter[]>, default: () => [] },
gridCurrents: Array,
prioritySoc: Number,
bufferSoc: Number,

View file

@ -11,6 +11,7 @@ const SETTINGS_ENERGYFLOW_DETAILS = "settings_energyflow_details";
const SETTINGS_ENERGYFLOW_PV = "settings_energyflow_pv";
const SETTINGS_ENERGYFLOW_BATTERY = "settings_energyflow_battery";
const SETTINGS_ENERGYFLOW_LOADPOINTS = "settings_energyflow_loadpoints";
const SETTINGS_ENERGYFLOW_CONSUMERS = "settings_energyflow_consumers";
const LOADPOINTS = "loadpoints";
const SESSION_COLUMNS = "session_columns";
const SAVINGS_PERIOD = "savings_period";
@ -94,6 +95,7 @@ export interface Settings {
energyflowPv: boolean;
energyflowBattery: boolean;
energyflowLoadpoints: boolean;
energyflowConsumers: boolean;
sessionColumns: string[];
savingsPeriod: string;
savingsRegion: string;
@ -113,6 +115,7 @@ const settings: Settings = reactive({
energyflowPv: readBool(SETTINGS_ENERGYFLOW_PV),
energyflowBattery: readBool(SETTINGS_ENERGYFLOW_BATTERY),
energyflowLoadpoints: readBool(SETTINGS_ENERGYFLOW_LOADPOINTS),
energyflowConsumers: readBool(SETTINGS_ENERGYFLOW_CONSUMERS),
sessionColumns: readArray(SESSION_COLUMNS),
savingsPeriod: read(SAVINGS_PERIOD),
savingsRegion: read(SAVINGS_REGION),
@ -131,6 +134,7 @@ watch(() => settings.energyflowDetails, saveBool(SETTINGS_ENERGYFLOW_DETAILS));
watch(() => settings.energyflowPv, saveBool(SETTINGS_ENERGYFLOW_PV));
watch(() => settings.energyflowBattery, saveBool(SETTINGS_ENERGYFLOW_BATTERY));
watch(() => settings.energyflowLoadpoints, saveBool(SETTINGS_ENERGYFLOW_LOADPOINTS));
watch(() => settings.energyflowConsumers, saveBool(SETTINGS_ENERGYFLOW_CONSUMERS));
watch(() => settings.sessionColumns as string[], saveArray(SESSION_COLUMNS));
watch(() => settings.savingsPeriod, save(SAVINGS_PERIOD));
watch(() => settings.savingsRegion, save(SAVINGS_REGION));

View file

@ -58,7 +58,10 @@ export interface State {
authProviders?: AuthProviders;
evopt?: EvOpt;
version?: string;
battery?: Battery[];
battery?: BatteryMeter[];
pv?: Meter[];
aux?: Meter[];
ext?: Meter[];
tariffGrid?: number;
tariffFeedIn?: number;
tariffCo2?: number;
@ -354,12 +357,17 @@ export interface Notification {
count: number;
}
export interface Battery {
export interface Meter {
power: number;
title?: string;
icon?: string;
energy?: number;
}
export interface BatteryMeter extends Meter {
soc: number;
controllable: boolean;
capacity: number; // 0 when not specified
title?: string;
}
export interface Vehicle {

View file

@ -133,6 +133,7 @@
"devices": {
"auxMeter": "Smarter Verbraucher",
"batteryStorage": "Batterie",
"consumer": "Verbraucher",
"solarSystem": "PV-Anlage"
},
"editor": {

View file

@ -133,6 +133,7 @@
"devices": {
"auxMeter": "Smart consumer",
"batteryStorage": "Battery storage",
"consumer": "Consumer",
"solarSystem": "Solar system"
},
"editor": {