Skip to content

Commit

Permalink
Fix home power and self-consumption calculation (evcc-io#1788)
Browse files Browse the repository at this point in the history
  • Loading branch information
naltatis authored Oct 26, 2021
1 parent 9969590 commit cbd0f23
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ lint-ui:
npm run lint

test-ui:
npm run test
npm test

test:
@echo "Running testsuite"
Expand Down
60 changes: 48 additions & 12 deletions assets/js/components/Energyflow/Energyflow.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ describe("Energyflow.vue", () => {
gridPower: 0,
pvConfigured: true,
pvPower: 0,
homePower: 0,
batteryConfigured: false,
batteryPower: 0,
batterySoC: 0,
Expand All @@ -25,15 +26,21 @@ 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");

expect(wrapper.find("[data-test-grid-import]").text()).toMatch("1.0 kW");
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);
Expand All @@ -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);
});

Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -102,6 +109,7 @@ describe("Energyflow.vue", () => {
pvPower: 0,
batteryConfigured: true,
batteryPower: 0,
homePower: 360,
},
});

Expand All @@ -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");
});
Expand All @@ -126,6 +134,7 @@ describe("Energyflow.vue", () => {
batteryPower: 234,
batterySoC: 77,
pvPower: 0,
homePower: 534,
},
});

Expand All @@ -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%");
Expand All @@ -151,6 +160,7 @@ describe("Energyflow.vue", () => {
batteryConfigured: true,
batteryPower: -1700,
pvPower: 9000,
homePower: 4800,
},
});

Expand All @@ -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");
Expand All @@ -175,6 +185,7 @@ describe("Energyflow.vue", () => {
batteryConfigured: true,
batteryPower: 1234,
pvPower: 378,
homePower: 7200,
},
});

Expand All @@ -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");
});
});
12 changes: 4 additions & 8 deletions assets/js/components/Energyflow/Energyflow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion core/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
Loading

0 comments on commit cbd0f23

Please sign in to comment.