Fix home power and self-consumption calculation (#1788)

This commit is contained in:
Michael Geers 2021-10-26 13:10:21 +02:00 • committed by GitHub
parent 9969590bd6
commit cbd0f23e73
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 65 additions and 28 deletions

View file

@ -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)

View file

@ -48,7 +48,7 @@ lint-ui:
npm run lint
test-ui:
npm run test
npm test
test:
@echo "Running testsuite"

View file

@ -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");
});
});

View file

@ -40,7 +40,7 @@
}}</span>
<span class="text-end text-nowrap ps-1">{{ kw(pvProduction) }}</span>
</div>
<div class="d-flex justify-content-between" data-test-house-consumption>
<div class="d-flex justify-content-between" data-test-home-power>
<span class="details-icon text-muted"><fa-icon icon="home"></fa-icon></span>
<span class="text-nowrap flex-grow-1">{{
$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);

View file

@ -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()
}

File diff suppressed because one or more lines are too long

4
dist/index.html vendored
View file

@ -1,4 +1,4 @@
<!DOCTYPE html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="EV Charge Controller"><meta name="author" content="andig"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="apple-touch-icon" sizes="180x180" href="ico/apple-touch-icon.png?[[.Version]]"><link rel="icon" type="image/png" sizes="32x32" href="ico/favicon-32x32.png?[[.Version]]"><link rel="icon" type="image/png" sizes="16x16" href="ico/favicon-16x16.png?[[.Version]]"><link rel="manifest" href="ico/site.webmanifest"><link rel="mask-icon" href="ico/safari-pinned-tab.svg?[[.Version]]" color="#18191a"><link rel="shortcut icon" href="ico/favicon.ico?[[.Version]]"><meta name="apple-mobile-web-app-title" content="evcc"><meta name="application-name" content="evcc"><meta name="msapplication-TileColor" content="#18191a"><meta name="msapplication-config" content="ico/browserconfig.xml"><meta name="theme-color" content="#18191a"><title>evcc</title><link href="css/chunk-vendors.595481b7.css" rel="preload" as="style"><link href="css/index.853953e0.css" rel="preload" as="style"><link href="js/chunk-vendors.d0133034.js" rel="preload" as="script"><link href="js/index.bf5040bb.js" rel="preload" as="script"><link href="css/chunk-vendors.595481b7.css" rel="stylesheet"><link href="css/index.853953e0.css" rel="stylesheet"></head><body><script>window.evcc = {
<!DOCTYPE html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="description" content="EV Charge Controller"><meta name="author" content="andig"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="apple-touch-icon" sizes="180x180" href="ico/apple-touch-icon.png?[[.Version]]"><link rel="icon" type="image/png" sizes="32x32" href="ico/favicon-32x32.png?[[.Version]]"><link rel="icon" type="image/png" sizes="16x16" href="ico/favicon-16x16.png?[[.Version]]"><link rel="manifest" href="ico/site.webmanifest"><link rel="mask-icon" href="ico/safari-pinned-tab.svg?[[.Version]]" color="#18191a"><link rel="shortcut icon" href="ico/favicon.ico?[[.Version]]"><meta name="apple-mobile-web-app-title" content="evcc"><meta name="application-name" content="evcc"><meta name="msapplication-TileColor" content="#18191a"><meta name="msapplication-config" content="ico/browserconfig.xml"><meta name="theme-color" content="#18191a"><title>evcc</title><link href="css/chunk-vendors.595481b7.css" rel="preload" as="style"><link href="css/index.364185a8.css" rel="preload" as="style"><link href="js/chunk-vendors.d0133034.js" rel="preload" as="script"><link href="js/index.daf0bdf4.js" rel="preload" as="script"><link href="css/chunk-vendors.595481b7.css" rel="stylesheet"><link href="css/index.364185a8.css" rel="stylesheet"></head><body><script>window.evcc = {
version: "[[.Version]]",
configured: "[[.Configured]]",
};</script><div id="app"></div><script src="js/chunk-vendors.d0133034.js"></script><script src="js/index.bf5040bb.js"></script></body></html>
};</script><div id="app"></div><script src="js/chunk-vendors.d0133034.js"></script><script src="js/index.daf0bdf4.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/js/index.daf0bdf4.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/index.daf0bdf4.js.map vendored Normal file

File diff suppressed because one or more lines are too long