Skip to content
17 changes: 8 additions & 9 deletions assets/js/components/Battery/BatterySettingsModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<div v-show="usageTabActive" class="row">
<p class="text-center text-md-start col-md-6 order-md-2 col-lg-3 order-lg-3 pt-lg-2">
{{ $t("batterySettings.batteryLevel") }}:
<strong>{{ fmtSoc(batterySoc) }}</strong>
<strong>{{ fmtSoc(battery?.soc ?? 0) }}</strong>
<small v-for="(line, index) in batteryDetails" :key="index" class="d-block">
{{ line }}
</small>
Expand Down Expand Up @@ -106,7 +106,7 @@
</div>
<div
class="batterySoc ps-0 bg-white pe-none"
:style="{ top: `${100 - batterySoc}%` }"
:style="{ top: `${100 - (battery?.soc ?? 100)}%` }"
></div>
<div
class="bufferStartIndicator pe-none"
Expand Down Expand Up @@ -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 { BatteryMeter, SelectOption, CURRENCY, Forecast } from "@/types/evcc";
import type { Battery, SelectOption, CURRENCY, Forecast } from "@/types/evcc";
import { SMART_COST_TYPE } from "@/types/evcc";

export default defineComponent({
Expand All @@ -274,10 +274,9 @@ export default defineComponent({
props: {
bufferSoc: { type: Number, default: 100 },
prioritySoc: { type: Number, default: 0 },
batterySoc: { type: Number, default: 0 },
bufferStartSoc: { type: Number, default: 0 },
batteryDischargeControl: Boolean,
battery: { type: Array as PropType<BatteryMeter[]>, default: () => [] },
battery: { type: Object as PropType<Battery> },
batteryGridChargeLimit: { type: Number, default: null },
smartCostAvailable: Boolean,
smartCostType: String as PropType<SMART_COST_TYPE>,
Expand Down Expand Up @@ -310,7 +309,7 @@ export default defineComponent({
return options;
},
controllable() {
return this.battery.some(({ controllable }) => controllable);
return this.battery && this.battery.devices.some(({ controllable }) => controllable);
},
gridChargePossible() {
return this.controllable && this.isModalVisible && this.smartCostAvailable;
Expand Down Expand Up @@ -366,13 +365,13 @@ export default defineComponent({
return this.prioritySoc;
},
batteryDetails() {
if (!Array.isArray(this.battery)) {
if (!this.battery) {
return;
}
return this.battery
const multipleBatteries = this.battery.devices.length > 1;
return this.battery.devices
.filter(({ capacity }) => capacity > 0)
.map(({ soc = 0, capacity }) => {
const multipleBatteries = this.battery.length > 1;
const energy = this.fmtWh(
(capacity / 100) * soc * 1e3,
POWER_UNIT.KW,
Expand Down
28 changes: 13 additions & 15 deletions assets/js/components/Energyflow/Energyflow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
:batteryHold="batteryHold"
:pvProduction="pvProduction"
:homePower="homePower"
:batterySoc="batterySoc"
:battery="battery"
:powerUnit="powerUnit"
:vehicleIcons="vehicleIcons"
:inPower="inPower"
Expand Down Expand Up @@ -113,10 +113,10 @@
:powerUnit="powerUnit"
:iconProps="{
hold: batteryHold,
soc: batterySoc,
soc: battery?.soc,
gridCharge: batteryGridChargeActive,
}"
:details="batterySoc"
:details="battery?.soc"
:detailsFmt="batteryFmt"
:expanded="batteryExpanded"
detailsClickable
Expand All @@ -127,9 +127,9 @@
<template v-if="batteryGridChargeLimitSet" #subline>
<div class="d-none d-md-block">&nbsp;</div>
</template>
<template v-if="battery.length > 1" #expanded>
<template v-if="battery && battery.devices.length > 1" #expanded>
<EnergyflowEntry
v-for="(b, index) in battery"
v-for="(b, index) in battery.devices"
:key="index"
:name="b.title || genericBatteryTitle(index)"
:details="b.soc"
Expand Down Expand Up @@ -231,10 +231,10 @@
:powerUnit="powerUnit"
:iconProps="{
hold: batteryHold,
soc: batterySoc,
soc: battery?.soc,
gridCharge: batteryGridChargeActive,
}"
:details="batterySoc"
:details="battery?.soc"
:detailsFmt="batteryFmt"
:expanded="batteryExpanded"
detailsClickable
Expand Down Expand Up @@ -262,9 +262,9 @@
</span>
</button>
</template>
<template v-if="battery.length > 1" #expanded>
<template v-if="battery && battery.devices.length > 1" #expanded>
<EnergyflowEntry
v-for="(b, index) in battery"
v-for="(b, index) in battery.devices"
:key="index"
:name="b.title || genericBatteryTitle(index)"
:details="b.soc"
Expand Down Expand Up @@ -304,7 +304,7 @@ import collector from "@/mixins/collector.js";
import { defineComponent, type PropType } from "vue";
import {
SMART_COST_TYPE,
type BatteryMeter,
type Battery,
type Meter,
type CURRENCY,
type Forecast,
Expand All @@ -330,9 +330,7 @@ export default defineComponent({
pvPower: { type: Number, default: 0 },
loadpoints: { type: Array as PropType<UiLoadpoint[]>, default: () => [] },
batteryConfigured: { type: Boolean },
battery: { type: Array as PropType<BatteryMeter[]>, default: () => [] },
batteryPower: { type: Number, default: 0 },
batterySoc: { type: Number, default: 0 },
battery: { type: Object as PropType<Battery> },
batteryDischargeControl: { type: Boolean },
batteryGridChargeLimit: { type: Number },
batteryGridChargeActive: { type: Boolean },
Expand Down Expand Up @@ -362,10 +360,10 @@ export default defineComponent({
return Math.abs(this.pvPower);
},
batteryDischarge() {
return this.dischargePower(this.batteryPower);
return this.dischargePower(this.battery?.power ?? 0);
},
batteryCharge() {
return this.chargePower(this.batteryPower);
return this.chargePower(this.battery?.power ?? 0);
},
batteryChargeLabel() {
return this.$t(`main.energyflow.battery${this.batteryHold ? "Hold" : "Charge"}`);
Expand Down
8 changes: 4 additions & 4 deletions assets/js/components/Energyflow/Visualization.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<shopicon-regular-sun></shopicon-regular-sun>
</LabelBar>
<LabelBar v-bind="labelBarProps('top', 'batteryDischarge')">
<BatteryIcon :soc="batterySoc" />
<BatteryIcon :soc="battery?.soc" />
</LabelBar>
<LabelBar v-bind="labelBarProps('top', 'gridImport')">
<shopicon-regular-powersupply></shopicon-regular-powersupply>
Expand Down Expand Up @@ -91,7 +91,7 @@
<VehicleIcon :names="[lp.icon]" />
</LabelBar>
<LabelBar v-bind="labelBarProps('bottom', 'batteryCharge')">
<BatteryIcon :soc="batterySoc" :gridCharge="batteryGridCharge" />
<BatteryIcon :soc="battery?.soc" :gridCharge="batteryGridCharge" />
</LabelBar>
<LabelBar v-bind="labelBarProps('bottom', 'gridExport')">
<shopicon-regular-powersupply></shopicon-regular-powersupply>
Expand All @@ -116,7 +116,7 @@ import QuestionIcon from "../MaterialIcon/Question.vue";
import "@h2d2/shopicons/es/regular/sun";
import "@h2d2/shopicons/es/regular/home";
import { defineComponent, type PropType } from "vue";
import type { UiLoadpoint } from "@/types/evcc";
import type { Battery, UiLoadpoint } from "@/types/evcc";

export default defineComponent({
name: "Visualization",
Expand All @@ -128,13 +128,13 @@ export default defineComponent({
selfBattery: { type: Number, default: 0 },
pvExport: { type: Number, default: 0 },
loadpoints: { type: Array as PropType<UiLoadpoint[]>, default: () => [] },
battery: { type: Object as PropType<Battery> },
batteryCharge: { type: Number, default: 0 },
batteryDischarge: { type: Number, default: 0 },
batteryHold: { type: Boolean, default: false },
batteryGridCharge: { type: Boolean, default: false },
pvProduction: { type: Number, default: 0 },
homePower: { type: Number, default: 0 },
batterySoc: { type: Number, default: 0 },
powerUnit: { type: String as PropType<POWER_UNIT>, default: POWER_UNIT.KW },
inPower: { type: Number, default: 0 },
outPower: { type: Number, default: 0 },
Expand Down
10 changes: 4 additions & 6 deletions assets/js/components/Site/Site.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
:gridConfigured="gridConfigured"
:pvConfigured="pvConfigured"
:batteryConfigured="batteryConfigured"
:batterySoc="batterySoc"
:batterySoc="battery?.soc"
:forecast="forecast"
:selectedId="selectedLoadpointId"
@id-changed="selectedLoadpointChanged"
Expand All @@ -87,7 +87,7 @@ import WelcomeIcons from "./WelcomeIcons.vue";
import { defineComponent, type PropType } from "vue";
import type {
AuthProviders,
BatteryMeter,
Battery,
Meter,
CURRENCY,
Forecast,
Expand Down Expand Up @@ -127,13 +127,11 @@ export default defineComponent({
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<BatteryMeter[]>, default: () => [] },
battery: { type: Object as PropType<Battery> },
gridCurrents: Array,
prioritySoc: Number,
bufferSoc: Number,
Expand Down Expand Up @@ -174,7 +172,7 @@ export default defineComponent({
return this.loadpoints.filter((lp) => lp.visible);
},
batteryConfigured() {
return this.battery?.length > 0;
return this.battery && this.battery.devices.length > 0;
},
pvConfigured() {
return this.pv?.length > 0;
Expand Down
6 changes: 3 additions & 3 deletions assets/js/components/Top/Navigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ import baseAPI from "./baseapi";
import { isApp, sendToApp } from "@/utils/native";
import { isUserConfigError } from "@/utils/fatal";
import { defineComponent, type PropType } from "vue";
import type { FatalError, Sponsor, AuthProviders, EvOpt } from "@/types/evcc";
import type { FatalError, Sponsor, AuthProviders, EvOpt, Battery } from "@/types/evcc";
import type { Provider as Provider } from "./types";

export default defineComponent({
Expand All @@ -150,7 +150,7 @@ export default defineComponent({
authProviders: { type: Object as PropType<AuthProviders>, default: () => ({}) },
sponsor: { type: Object as PropType<Sponsor>, default: () => ({}) },
forecast: Object,
battery: Array,
battery: { type: Object as PropType<Battery> },
evopt: { type: Object as PropType<EvOpt>, required: false },
fatal: { type: Array as PropType<FatalError[]>, default: () => [] },
},
Expand All @@ -162,7 +162,7 @@ export default defineComponent({
},
computed: {
batteryConfigured() {
return this.battery?.length;
return this.battery && this.battery.devices.length;
},
providerLogins(): Provider[] {
return Object.entries(this.authProviders).map(([title, { authenticated, id }]) => ({
Expand Down
9 changes: 8 additions & 1 deletion assets/js/types/evcc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export interface State {
authProviders?: AuthProviders;
evopt?: EvOpt;
version?: string;
battery?: BatteryMeter[];
battery?: Battery;
pv?: Meter[];
aux?: Meter[];
ext?: Meter[];
Expand Down Expand Up @@ -364,6 +364,13 @@ export interface Meter {
energy?: number;
}

export interface Battery {
power: number;
capacity: number;
soc: number;
devices: BatteryMeter[];
}

export interface BatteryMeter extends Meter {
soc: number;
controllable: boolean;
Expand Down
8 changes: 6 additions & 2 deletions assets/js/views/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
<router-view :notifications="notifications" :offline="offline"></router-view>

<GlobalSettingsModal v-bind="globalSettingsProps" />
<BatterySettingsModal v-if="batteryModalAvailabe" v-bind="batterySettingsProps" />
<BatterySettingsModal
v-if="batteryModalAvailabe"
v-bind="batterySettingsProps"
:battery="state.battery"
/>
<ForecastModal v-bind="forecastModalProps" />
<HelpModal />
<PasswordModal />
Expand Down Expand Up @@ -65,7 +69,7 @@ export default defineComponent({
return store.state.version;
},
batteryModalAvailabe() {
return store.state.battery?.length;
return store.state.battery?.devices.length;
},
state() {
const { state, uiLoadpoints } = store;
Expand Down
8 changes: 2 additions & 6 deletions core/keys/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,15 @@ const (
AuxMeters = "auxMeters"

// battery settings
BatteryCapacity = "batteryCapacity"
BatteryDischargeControl = "batteryDischargeControl"
BatteryGridChargeLimit = "batteryGridChargeLimit"
BatteryGridChargeActive = "batteryGridChargeActive"
BufferSoc = "bufferSoc"
BufferStartSoc = "bufferStartSoc"

// battery status
Battery = "battery"
BatteryEnergy = "batteryEnergy"
BatteryMode = "batteryMode"
BatteryPower = "batteryPower"
BatterySoc = "batterySoc"
Battery = "battery"
BatteryMode = "batteryMode"

// external battery control
BatteryModeExternal = "batteryModeExternal"
Expand Down
Loading
Loading