diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6c25e28a7..b2a55342e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -78,6 +78,9 @@ jobs:
- name: Lint
run: make lint-ui
+ - name: Test
+ run: make test-ui
+
- name: Porcelain
run: |
test -z "$(git status --porcelain)" || (git status; git diff; false)
diff --git a/Makefile b/Makefile
index 3150418f9..b92690ffc 100644
--- a/Makefile
+++ b/Makefile
@@ -48,7 +48,7 @@ lint-ui:
npm run lint
test-ui:
- npm run test
+ npm test
test:
@echo "Running testsuite"
diff --git a/assets/js/components/Energyflow/Energyflow.spec.js b/assets/js/components/Energyflow/Energyflow.spec.js
index 105650e3d..7e1ee03dd 100644
--- a/assets/js/components/Energyflow/Energyflow.spec.js
+++ b/assets/js/components/Energyflow/Energyflow.spec.js
@@ -17,6 +17,7 @@ describe("Energyflow.vue", () => {
gridPower: 0,
pvConfigured: true,
pvPower: 0,
+ homePower: 0,
batteryConfigured: false,
batteryPower: 0,
batterySoC: 0,
@@ -25,7 +26,13 @@ describe("Energyflow.vue", () => {
it("using pv and grid power", async () => {
const wrapper = shallowMount(Energyflow, {
mocks,
- propsData: { ...defaultProps, gridPower: 1000, pvPower: 4000, loadpointsPower: 3700 },
+ propsData: {
+ ...defaultProps,
+ gridPower: 1000,
+ pvPower: 4000,
+ homePower: 1300,
+ loadpointsPower: 3700,
+ },
});
await wrapper.find(".energyflow").trigger("click");
@@ -33,7 +40,7 @@ describe("Energyflow.vue", () => {
expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("4.0 kW");
expect(wrapper.find("[data-test-pv-export]").text()).toMatch("0.0 kW");
- expect(wrapper.find("[data-test-house-consumption]").text()).toMatch("1.3 kW");
+ expect(wrapper.find("[data-test-home-power]").text()).toMatch("1.3 kW");
expect(wrapper.find("[data-test-loadpoints]").text()).toMatch("3.7 kW");
expect(wrapper.find("[data-test-pv-production]").text()).toMatch("4.0 kW");
expect(wrapper.find("[data-test-battery]").exists()).toBe(false);
@@ -42,18 +49,18 @@ describe("Energyflow.vue", () => {
it("exporting all pv power, no usage", async () => {
const wrapper = shallowMount(Energyflow, {
mocks,
- propsData: { ...defaultProps, gridPower: -4000, pvPower: 4000, loadpointsPower: 1000 },
+ propsData: { ...defaultProps, gridPower: -4000, pvPower: 5000, loadpointsPower: 1000 },
});
await wrapper.find(".energyflow").trigger("click");
expect(wrapper.find("[data-test-grid-import]").text()).toMatch("0.0 kW");
- expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("0.0 kW");
+ expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("1.0 kW");
expect(wrapper.find("[data-test-pv-export]").text()).toMatch("4.0 kW");
- expect(wrapper.find("[data-test-house-consumption]").text()).toMatch("0.0 kW");
+ expect(wrapper.find("[data-test-home-power]").text()).toMatch("0.0 kW");
expect(wrapper.find("[data-test-loadpoints]").text()).toMatch("1.0 kW");
- expect(wrapper.find("[data-test-pv-production]").text()).toMatch("4.0 kW");
+ expect(wrapper.find("[data-test-pv-production]").text()).toMatch("5.0 kW");
expect(wrapper.find("[data-test-battery]").exists()).toBe(false);
});
@@ -69,7 +76,7 @@ describe("Energyflow.vue", () => {
expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("0.0 kW");
expect(wrapper.find("[data-test-pv-export]").text()).toMatch("4.0 kW");
- expect(wrapper.find("[data-test-house-consumption]").text()).toMatch("0.0 kW");
+ expect(wrapper.find("[data-test-home-power]").text()).toMatch("0.0 kW");
expect(wrapper.find("[data-test-loadpoints]").text()).toMatch("0.0 kW");
expect(wrapper.find("[data-test-pv-production]").text()).toMatch("3.0 kW");
expect(wrapper.find("[data-test-battery]").exists()).toBe(false);
@@ -87,7 +94,7 @@ describe("Energyflow.vue", () => {
expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("0.0 kW");
expect(wrapper.find("[data-test-pv-export]").text()).toMatch("0.0 kW");
- expect(wrapper.find("[data-test-house-consumption]").text()).toMatch("0.0 kW");
+ expect(wrapper.find("[data-test-home-power]").text()).toMatch("0.0 kW");
expect(wrapper.find("[data-test-loadpoints]").text()).toMatch("7.0 kW");
expect(wrapper.find("[data-test-pv-production]").text()).toMatch("0.0 kW");
expect(wrapper.find("[data-test-battery]").exists()).toBe(false);
@@ -102,6 +109,7 @@ describe("Energyflow.vue", () => {
pvPower: 0,
batteryConfigured: true,
batteryPower: 0,
+ homePower: 360,
},
});
@@ -111,7 +119,7 @@ describe("Energyflow.vue", () => {
expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("0 W");
expect(wrapper.find("[data-test-pv-export]").text()).toMatch("0 W");
- expect(wrapper.find("[data-test-house-consumption]").text()).toMatch("360 W");
+ expect(wrapper.find("[data-test-home-power]").text()).toMatch("360 W");
expect(wrapper.find("[data-test-pv-production]").text()).toMatch("0 W");
expect(wrapper.find("[data-test-battery]").text()).toMatch("main.energyflow.battery");
});
@@ -126,6 +134,7 @@ describe("Energyflow.vue", () => {
batteryPower: 234,
batterySoC: 77,
pvPower: 0,
+ homePower: 534,
},
});
@@ -135,7 +144,7 @@ describe("Energyflow.vue", () => {
expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("234 W");
expect(wrapper.find("[data-test-pv-export]").text()).toMatch("0 W");
- expect(wrapper.find("[data-test-house-consumption]").text()).toMatch("534 W");
+ expect(wrapper.find("[data-test-home-power]").text()).toMatch("534 W");
expect(wrapper.find("[data-test-pv-production]").text()).toMatch("0 W");
expect(wrapper.find("[data-test-battery]").text()).toMatch("234 W");
expect(wrapper.find("[data-test-battery]").text()).toMatch("77%");
@@ -151,6 +160,7 @@ describe("Energyflow.vue", () => {
batteryConfigured: true,
batteryPower: -1700,
pvPower: 9000,
+ homePower: 4800,
},
});
@@ -160,7 +170,7 @@ describe("Energyflow.vue", () => {
expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("6.5 kW");
expect(wrapper.find("[data-test-pv-export]").text()).toMatch("2.5 kW");
- expect(wrapper.find("[data-test-house-consumption]").text()).toMatch("4.8 kW");
+ expect(wrapper.find("[data-test-home-power]").text()).toMatch("4.8 kW");
expect(wrapper.find("[data-test-pv-production]").text()).toMatch("9.0 kW");
expect(wrapper.find("[data-test-battery]").text()).toMatch("1.7 kW");
expect(wrapper.find("[data-test-battery]").text()).toMatch("main.energyflow.batteryCharge");
@@ -175,6 +185,7 @@ describe("Energyflow.vue", () => {
batteryConfigured: true,
batteryPower: 1234,
pvPower: 378,
+ homePower: 7200,
},
});
@@ -184,9 +195,34 @@ describe("Energyflow.vue", () => {
expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("1.6 kW");
expect(wrapper.find("[data-test-pv-export]").text()).toMatch("0.0 kW");
- expect(wrapper.find("[data-test-house-consumption]").text()).toMatch("7.2 kW");
+ expect(wrapper.find("[data-test-home-power]").text()).toMatch("7.2 kW");
expect(wrapper.find("[data-test-pv-production]").text()).toMatch("0.4 kW");
expect(wrapper.find("[data-test-battery]").text()).toMatch("1.2 kW");
expect(wrapper.find("[data-test-battery]").text()).toMatch("main.energyflow.batteryDischarge");
});
+
+ it("battery charge, grid import", async () => {
+ const wrapper = shallowMount(Energyflow, {
+ mocks,
+ propsData: {
+ ...defaultProps,
+ gridPower: 1500,
+ batteryConfigured: true,
+ batteryPower: -1000,
+ homePower: 500,
+ pvPower: 0,
+ },
+ });
+
+ await wrapper.find(".energyflow").trigger("click");
+
+ expect(wrapper.find("[data-test-grid-import]").text()).toMatch("1.5 kW");
+ expect(wrapper.find("[data-test-self-consumption]").text()).toMatch("0.0 kW");
+ expect(wrapper.find("[data-test-pv-export]").text()).toMatch("0.0 kW");
+
+ expect(wrapper.find("[data-test-home-power]").text()).toMatch("0.5 kW");
+ expect(wrapper.find("[data-test-pv-production]").text()).toMatch("0.0 kW");
+ expect(wrapper.find("[data-test-battery]").text()).toMatch("1.0 kW");
+ expect(wrapper.find("[data-test-battery]").text()).toMatch("main.energyflow.batteryCharge");
+ });
});
diff --git a/assets/js/components/Energyflow/Energyflow.vue b/assets/js/components/Energyflow/Energyflow.vue
index 954f7b2fe..488b6b798 100644
--- a/assets/js/components/Energyflow/Energyflow.vue
+++ b/assets/js/components/Energyflow/Energyflow.vue
@@ -40,7 +40,7 @@
}}
{{ kw(pvProduction) }}
-
+
{{
$t("main.energyflow.homePower")
@@ -159,12 +159,6 @@ export default {
pvProduction: function () {
return this.pvConfigured ? Math.abs(this.pvPower) : this.pvExport;
},
- pvConsumption: function () {
- return Math.min(
- this.pvProduction,
- this.pvProduction + this.gridPower - this.batteryCharge
- );
- },
batteryPowerAdjusted: function () {
const batteryPowerThreshold = 50;
return Math.abs(this.batteryPower) < batteryPowerThreshold ? 0 : this.batteryPower;
@@ -176,7 +170,9 @@ export default {
return Math.min(0, this.batteryPowerAdjusted) * -1;
},
selfConsumption: function () {
- return Math.max(0, this.batteryDischarge + this.pvConsumption + this.batteryCharge);
+ const ownPower = this.batteryDischarge + this.pvProduction;
+ const consumption = this.homePower + this.batteryCharge + this.loadpointsPower;
+ return Math.min(ownPower, consumption);
},
pvExport: function () {
return Math.max(0, this.gridPower * -1);
diff --git a/core/site.go b/core/site.go
index fd243961d..0f90aa7a8 100644
--- a/core/site.go
+++ b/core/site.go
@@ -390,7 +390,9 @@ func (site *Site) update(lp Updater) {
if sitePower, err := site.sitePower(); err == nil {
lp.Update(sitePower, cheap, site.batteryBuffered)
- homePower := site.gridPower + site.pvPower + site.batteryPower
+ gridImport := math.Max(0, site.gridPower)
+
+ homePower := gridImport + site.pvPower + site.batteryPower
for _, lp := range site.loadpoints {
homePower -= lp.GetChargePower()
}
diff --git a/dist/css/index.853953e0.css b/dist/css/index.364185a8.css
similarity index 95%
rename from dist/css/index.853953e0.css
rename to dist/css/index.364185a8.css
index 1ea0e4969..b5c8c8eb5 100644
--- a/dist/css/index.853953e0.css
+++ b/dist/css/index.364185a8.css
@@ -1 +1 @@
-:root{--evcc-green:#66d85a;--evcc-dark-green:#3aba2c;--evcc-yellow:#ffe000;--evcc-grid:var(--bs-gray-dark);--evcc-self:var(--evcc-dark-green);--evcc-export:var(--evcc-yellow);--bs-primary:var(--evcc-dark-green);--bs-primary-rgb:58,186,44}.bg-primary{background-color:var(--evcc-dark-green)!important}a{color:var(--evcc-dark-green)}.progress-bar-animated{animation-direction:reverse}.bg-muted{opacity:.25}.btn-primary{background-color:var(--bs-gray-dark);border-color:var(--bs-gray-dark)}.btn-primary:hover{background-color:var(--evcc-dark-green);border-color:var(--evcc-dark-green)}.icon[data-v-785de62e]{color:#0fdd42}.icon[data-v-1eecc7b7]{color:#0fdd42;display:inline-block}.sponsor-button[data-v-1eecc7b7]{touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.support-button .solid[data-v-1eecc7b7]{display:none}.support-button:hover .solid[data-v-1eecc7b7]{display:inline-block}.support-button:hover .outline[data-v-1eecc7b7]{display:none}.logo[data-v-7f4d7df3]{width:85px}.app[data-v-7f4d7df3]{min-height:100vh}.title[data-v-7f4d7df3]{position:relative;top:.1rem}.battery[data-v-2dcca16c]{transform:translateX(.35rem) rotate(-90deg);transition-property:transform;transition-duration:.25s;transition-timing-function:ease}.power--in .battery[data-v-2dcca16c]{transform:translateX(.7rem) rotate(-90deg)}.power--out .battery[data-v-2dcca16c]{transform:translateX(0) rotate(-90deg)}.arrow[data-v-2dcca16c]{margin-left:-.2rem;opacity:0;transform:translateX(-.5rem);transition-property:opacity,transform;transition-duration:.25s;transition-timing-function:ease}.power--in .arrow[data-v-2dcca16c]{opacity:1;transform:translateX(-1rem) scaleX(1)}.power--out .arrow[data-v-2dcca16c]{opacity:1;transform:translateX(0) scaleX(1)}.grid[data-v-c8e84f48]{transform:translateX(.35rem);transition-property:transform;transition-duration:.25s;transition-timing-function:ease}.power-export .grid[data-v-c8e84f48]{transform:translateX(.9rem)}.power-import .grid[data-v-c8e84f48]{transform:translateX(-.1rem)}.arrow[data-v-c8e84f48]{margin-left:-.2rem;opacity:0;transform:translateX(-.5rem);transition-property:opacity,transform;transition-duration:.25s;transition-timing-function:ease}.power-export .arrow[data-v-c8e84f48]{opacity:1;transform:translateX(-.9rem) scaleX(1)}.power-import .arrow[data-v-c8e84f48]{opacity:1;transform:translateX(.1em) scaleX(1)}.label-bar[data-v-17da7e54]{width:0;margin:0;height:1.7rem;padding:.6rem 0;opacity:1;overflow:hidden}.label-bar-scale--hidden[data-v-17da7e54]{opacity:0}.label-bar-scale[data-v-17da7e54]{border:1px solid var(--bs-gray);height:.5rem;background:none;display:flex;justify-content:center;align-items:center;white-space:nowrap;border-radius:0;transition:border-radius .5s linear}.label-bar--top .label-bar-scale[data-v-17da7e54]{border-bottom:none}.label-bar--bottom .label-bar-scale[data-v-17da7e54]{border-top:none}.label-bar--top.label-bar--first .label-bar-scale[data-v-17da7e54]{border-top-left-radius:4px}.label-bar--top.label-bar--last .label-bar-scale[data-v-17da7e54]{border-top-right-radius:4px}.label-bar--bottom.label-bar--first .label-bar-scale[data-v-17da7e54]{border-bottom-left-radius:4px}.label-bar--bottom.label-bar--last .label-bar-scale[data-v-17da7e54]{border-bottom-right-radius:4px}.label-bar:not(.label-bar--first) .label-bar-scale[data-v-17da7e54]{border-left:none}.label-bar-icon[data-v-17da7e54]{background-color:#fff;color:var(--bs-gray);padding:0 .3rem;opacity:1}.label-bar--top .label-bar-icon[data-v-17da7e54]{margin-top:-6px}.label-bar--bottom .label-bar-icon[data-v-17da7e54]{margin-top:6px}.label-bar--hidden[data-v-17da7e54],.label-bar--hide-icon .label-bar-icon[data-v-17da7e54]{opacity:0}.site-progress[data-v-4cea1228]{--height:38px;height:var(--height);margin:.25rem 0;border-radius:5px;display:flex;overflow:hidden}.site-progress-bar[data-v-4cea1228]{display:flex;justify-content:center;align-items:center;overflow:hidden;position:relative;width:0}.visualization--ready .site-progress-bar[data-v-4cea1228]{transition-property:width;transition-duration:.5s;transition-timing-function:linear}.grid-import[data-v-4cea1228]{background-color:var(--evcc-grid);color:var(--bs-white)}.self-consumption[data-v-4cea1228]{background-color:var(--evcc-self);color:var(--bs-white)}.pv-export[data-v-4cea1228]{background-color:var(--evcc-export);color:var(--bs-dark)}.power[data-v-4cea1228]{display:block;margin:0 .2rem;white-space:nowrap;overflow:hidden}.visualization--ready[data-v-4cea1228] .label-bar{transition-property:width,opacity;transition-duration:.5s,.25s;transition-timing-function:linear,ease}.visualization--ready[data-v-4cea1228] .label-bar-icon{transition:opacity .25s ease-in}.energyflow[data-v-47b5e1ea]{cursor:pointer}.color-grid[data-v-47b5e1ea]{color:var(--evcc-grid)}.color-self[data-v-47b5e1ea]{color:var(--evcc-self)}.color-export[data-v-47b5e1ea]{color:var(--evcc-export)}.details-icon[data-v-47b5e1ea]{text-align:center;width:30px;margin-right:.25rem;white-space:nowrap;flex-shrink:0}.btn[data-v-1ff39d22]{flex-basis:0;white-space:nowrap}.vehicle-soc[data-v-0264df98]{--height:38px;--thumb-overlap:3px;--thumb-width:3px;--thumb-horizontal-padding:15px;--label-height:26px;position:relative;height:var(--height)}.progress[data-v-0264df98]{height:100%;font-size:1rem}.progress-bar.bg-muted[data-v-0264df98]{color:var(--white)}.bg-light[data-v-0264df98]{color:var(--bs-gray-dark)}.target-label[data-v-0264df98]{width:3em;margin-left:-1.5em;height:var(--label-height);position:absolute;top:calc(var(--label-height)*-1 + var(--thumb-overlap)*-1);text-align:center;color:var(--bs-gray-dark);font-size:1rem;opacity:1;transition:opacity .2s ease 1s}.target-slider[data-v-0264df98]{-webkit-appearance:none;position:absolute;top:calc(var(--thumb-overlap)*-1);left:calc(var(--thumb-horizontal-padding)*-1);height:calc(100% + var(--thumb-overlap)*2);width:calc(100% + var(--thumb-horizontal-padding)*2);background:transparent}.target-slider[data-v-0264df98]:focus{outline:none}.target-slider[data-v-0264df98]::-webkit-slider-runnable-track{position:relative;background:transparent;border:none;height:100%;cursor:pointer}.target-slider[data-v-0264df98]::-moz-range-track{background:transparent;border:none;height:100%;cursor:pointer}.target-slider[data-v-0264df98]::-webkit-slider-thumb{-webkit-appearance:none;position:relative;top:calc(var(--label-height)*-1);height:100%;width:var(--thumb-width);padding:var(--label-height) var(--thumb-horizontal-padding) 0;box-sizing:content-box;background-clip:content-box;background-color:var(--bs-gray-dark);cursor:-webkit-grab;cursor:grab;border:none;opacity:1;-webkit-transition:opacity .2s ease 1s;transition:opacity .2s ease 1s;box-shadow:none}.target-slider[data-v-0264df98]::-moz-range-thumb{position:relative;top:calc(var(--label-height)*-1);height:100%;width:var(--thumb-width);padding:0 var(--thumb-horizontal-padding) 0;box-sizing:content-box;background-clip:content-box;background-color:var(--bs-gray-dark);cursor:grab;border:none;opacity:1;-moz-transition:opacity .5s ease 1s;transition:opacity .5s ease 1s}.target--slider-hidden .target-label[data-v-0264df98],.target--slider-hidden .target-slider[data-v-0264df98]::-webkit-slider-thumb{opacity:0}.target--slider-hidden .target-label[data-v-0264df98],.target--slider-hidden .target-slider[data-v-0264df98]::-moz-range-thumb{opacity:0}.target:hover .target-label[data-v-0264df98],.target:hover .target-slider[data-v-0264df98]::-webkit-slider-thumb{opacity:1;transition-delay:0s}.target:hover .target-label[data-v-0264df98],.target:hover .target-slider[data-v-0264df98]::-moz-range-thumb{opacity:1;transition-delay:0s}
\ No newline at end of file
+:root{--evcc-green:#66d85a;--evcc-dark-green:#3aba2c;--evcc-yellow:#ffe000;--evcc-grid:var(--bs-gray-dark);--evcc-self:var(--evcc-dark-green);--evcc-export:var(--evcc-yellow);--bs-primary:var(--evcc-dark-green);--bs-primary-rgb:58,186,44}.bg-primary{background-color:var(--evcc-dark-green)!important}a{color:var(--evcc-dark-green)}.progress-bar-animated{animation-direction:reverse}.bg-muted{opacity:.25}.btn-primary{background-color:var(--bs-gray-dark);border-color:var(--bs-gray-dark)}.btn-primary:hover{background-color:var(--evcc-dark-green);border-color:var(--evcc-dark-green)}.icon[data-v-785de62e]{color:#0fdd42}.icon[data-v-1eecc7b7]{color:#0fdd42;display:inline-block}.sponsor-button[data-v-1eecc7b7]{touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.support-button .solid[data-v-1eecc7b7]{display:none}.support-button:hover .solid[data-v-1eecc7b7]{display:inline-block}.support-button:hover .outline[data-v-1eecc7b7]{display:none}.logo[data-v-7f4d7df3]{width:85px}.app[data-v-7f4d7df3]{min-height:100vh}.title[data-v-7f4d7df3]{position:relative;top:.1rem}.battery[data-v-2dcca16c]{transform:translateX(.35rem) rotate(-90deg);transition-property:transform;transition-duration:.25s;transition-timing-function:ease}.power--in .battery[data-v-2dcca16c]{transform:translateX(.7rem) rotate(-90deg)}.power--out .battery[data-v-2dcca16c]{transform:translateX(0) rotate(-90deg)}.arrow[data-v-2dcca16c]{margin-left:-.2rem;opacity:0;transform:translateX(-.5rem);transition-property:opacity,transform;transition-duration:.25s;transition-timing-function:ease}.power--in .arrow[data-v-2dcca16c]{opacity:1;transform:translateX(-1rem) scaleX(1)}.power--out .arrow[data-v-2dcca16c]{opacity:1;transform:translateX(0) scaleX(1)}.grid[data-v-c8e84f48]{transform:translateX(.35rem);transition-property:transform;transition-duration:.25s;transition-timing-function:ease}.power-export .grid[data-v-c8e84f48]{transform:translateX(.9rem)}.power-import .grid[data-v-c8e84f48]{transform:translateX(-.1rem)}.arrow[data-v-c8e84f48]{margin-left:-.2rem;opacity:0;transform:translateX(-.5rem);transition-property:opacity,transform;transition-duration:.25s;transition-timing-function:ease}.power-export .arrow[data-v-c8e84f48]{opacity:1;transform:translateX(-.9rem) scaleX(1)}.power-import .arrow[data-v-c8e84f48]{opacity:1;transform:translateX(.1em) scaleX(1)}.label-bar[data-v-17da7e54]{width:0;margin:0;height:1.7rem;padding:.6rem 0;opacity:1;overflow:hidden}.label-bar-scale--hidden[data-v-17da7e54]{opacity:0}.label-bar-scale[data-v-17da7e54]{border:1px solid var(--bs-gray);height:.5rem;background:none;display:flex;justify-content:center;align-items:center;white-space:nowrap;border-radius:0;transition:border-radius .5s linear}.label-bar--top .label-bar-scale[data-v-17da7e54]{border-bottom:none}.label-bar--bottom .label-bar-scale[data-v-17da7e54]{border-top:none}.label-bar--top.label-bar--first .label-bar-scale[data-v-17da7e54]{border-top-left-radius:4px}.label-bar--top.label-bar--last .label-bar-scale[data-v-17da7e54]{border-top-right-radius:4px}.label-bar--bottom.label-bar--first .label-bar-scale[data-v-17da7e54]{border-bottom-left-radius:4px}.label-bar--bottom.label-bar--last .label-bar-scale[data-v-17da7e54]{border-bottom-right-radius:4px}.label-bar:not(.label-bar--first) .label-bar-scale[data-v-17da7e54]{border-left:none}.label-bar-icon[data-v-17da7e54]{background-color:#fff;color:var(--bs-gray);padding:0 .3rem;opacity:1}.label-bar--top .label-bar-icon[data-v-17da7e54]{margin-top:-6px}.label-bar--bottom .label-bar-icon[data-v-17da7e54]{margin-top:6px}.label-bar--hidden[data-v-17da7e54],.label-bar--hide-icon .label-bar-icon[data-v-17da7e54]{opacity:0}.site-progress[data-v-4cea1228]{--height:38px;height:var(--height);margin:.25rem 0;border-radius:5px;display:flex;overflow:hidden}.site-progress-bar[data-v-4cea1228]{display:flex;justify-content:center;align-items:center;overflow:hidden;position:relative;width:0}.visualization--ready .site-progress-bar[data-v-4cea1228]{transition-property:width;transition-duration:.5s;transition-timing-function:linear}.grid-import[data-v-4cea1228]{background-color:var(--evcc-grid);color:var(--bs-white)}.self-consumption[data-v-4cea1228]{background-color:var(--evcc-self);color:var(--bs-white)}.pv-export[data-v-4cea1228]{background-color:var(--evcc-export);color:var(--bs-dark)}.power[data-v-4cea1228]{display:block;margin:0 .2rem;white-space:nowrap;overflow:hidden}.visualization--ready[data-v-4cea1228] .label-bar{transition-property:width,opacity;transition-duration:.5s,.25s;transition-timing-function:linear,ease}.visualization--ready[data-v-4cea1228] .label-bar-icon{transition:opacity .25s ease-in}.energyflow[data-v-e1aa7340]{cursor:pointer}.color-grid[data-v-e1aa7340]{color:var(--evcc-grid)}.color-self[data-v-e1aa7340]{color:var(--evcc-self)}.color-export[data-v-e1aa7340]{color:var(--evcc-export)}.details-icon[data-v-e1aa7340]{text-align:center;width:30px;margin-right:.25rem;white-space:nowrap;flex-shrink:0}.btn[data-v-1ff39d22]{flex-basis:0;white-space:nowrap}.vehicle-soc[data-v-0264df98]{--height:38px;--thumb-overlap:3px;--thumb-width:3px;--thumb-horizontal-padding:15px;--label-height:26px;position:relative;height:var(--height)}.progress[data-v-0264df98]{height:100%;font-size:1rem}.progress-bar.bg-muted[data-v-0264df98]{color:var(--white)}.bg-light[data-v-0264df98]{color:var(--bs-gray-dark)}.target-label[data-v-0264df98]{width:3em;margin-left:-1.5em;height:var(--label-height);position:absolute;top:calc(var(--label-height)*-1 + var(--thumb-overlap)*-1);text-align:center;color:var(--bs-gray-dark);font-size:1rem;opacity:1;transition:opacity .2s ease 1s}.target-slider[data-v-0264df98]{-webkit-appearance:none;position:absolute;top:calc(var(--thumb-overlap)*-1);left:calc(var(--thumb-horizontal-padding)*-1);height:calc(100% + var(--thumb-overlap)*2);width:calc(100% + var(--thumb-horizontal-padding)*2);background:transparent}.target-slider[data-v-0264df98]:focus{outline:none}.target-slider[data-v-0264df98]::-webkit-slider-runnable-track{position:relative;background:transparent;border:none;height:100%;cursor:pointer}.target-slider[data-v-0264df98]::-moz-range-track{background:transparent;border:none;height:100%;cursor:pointer}.target-slider[data-v-0264df98]::-webkit-slider-thumb{-webkit-appearance:none;position:relative;top:calc(var(--label-height)*-1);height:100%;width:var(--thumb-width);padding:var(--label-height) var(--thumb-horizontal-padding) 0;box-sizing:content-box;background-clip:content-box;background-color:var(--bs-gray-dark);cursor:-webkit-grab;cursor:grab;border:none;opacity:1;-webkit-transition:opacity .2s ease 1s;transition:opacity .2s ease 1s;box-shadow:none}.target-slider[data-v-0264df98]::-moz-range-thumb{position:relative;top:calc(var(--label-height)*-1);height:100%;width:var(--thumb-width);padding:0 var(--thumb-horizontal-padding) 0;box-sizing:content-box;background-clip:content-box;background-color:var(--bs-gray-dark);cursor:grab;border:none;opacity:1;-moz-transition:opacity .5s ease 1s;transition:opacity .5s ease 1s}.target--slider-hidden .target-label[data-v-0264df98],.target--slider-hidden .target-slider[data-v-0264df98]::-webkit-slider-thumb{opacity:0}.target--slider-hidden .target-label[data-v-0264df98],.target--slider-hidden .target-slider[data-v-0264df98]::-moz-range-thumb{opacity:0}.target:hover .target-label[data-v-0264df98],.target:hover .target-slider[data-v-0264df98]::-webkit-slider-thumb{opacity:1;transition-delay:0s}.target:hover .target-label[data-v-0264df98],.target:hover .target-slider[data-v-0264df98]::-moz-range-thumb{opacity:1;transition-delay:0s}
\ No newline at end of file
diff --git a/dist/index.html b/dist/index.html
index c97a9e13d..7bf357ec5 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -1,4 +1,4 @@
-evcc
\ No newline at end of file
+ };