Skip to content

More support for no-grid energy dashboard #25644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions src/panels/energy/strategies/energy-view-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ export class EnergyViewStrategy extends ReactiveElement {
(source) => source.type === "solar"
);
const hasGas = prefs.energy_sources.some((source) => source.type === "gas");

const hasBattery = prefs.energy_sources.some(
(source) => source.type === "battery"
);
const hasWater = prefs.energy_sources.some(
(source) => source.type === "water"
);
Expand All @@ -74,8 +76,8 @@ export class EnergyViewStrategy extends ReactiveElement {
collection_key: "energy_dashboard",
});

// Only include if we have a grid source.
if (hasGrid) {
// Only include if we have a grid or battery.
if (hasGrid || hasBattery) {
view.cards!.push({
title: hass.localize("ui.panel.energy.cards.energy_usage_graph_title"),
type: "energy-usage-graph",
Expand Down Expand Up @@ -110,8 +112,8 @@ export class EnergyViewStrategy extends ReactiveElement {
});
}

// Only include if we have a grid.
if (hasGrid) {
// Only include if we have a grid or battery.
if (hasGrid || hasBattery) {
view.cards!.push({
title: hass.localize("ui.panel.energy.cards.energy_distribution_title"),
type: "energy-distribution",
Expand All @@ -120,7 +122,7 @@ export class EnergyViewStrategy extends ReactiveElement {
});
}

if (hasGrid || hasSolar || hasGas || hasWater) {
if (hasGrid || hasSolar || hasGas || hasWater || hasBattery) {
view.cards!.push({
title: hass.localize(
"ui.panel.energy.cards.energy_sources_table_title"
Expand Down
157 changes: 90 additions & 67 deletions src/panels/lovelace/cards/energy/hui-energy-distribution-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,13 @@ class HuiEnergyDistrubutionCard
const prefs = this._data.prefs;
const types = energySourcesByType(prefs);

// The strategy only includes this card if we have a grid.
const hasConsumption = true;

const hasGrid =
!!types.grid?.[0].flow_from.length || !!types.grid?.[0].flow_to.length;
const hasSolarProduction = types.solar !== undefined;
const hasBattery = types.battery !== undefined;
const hasGas = types.gas !== undefined;
const hasWater = types.water !== undefined;
const hasReturnToGrid = hasConsumption && types.grid![0].flow_to.length > 0;
const hasReturnToGrid = !!types.grid?.[0].flow_to.length;

const { summedData, compareSummedData: _ } = getSummedData(this._data);
const { consumption, compareConsumption: __ } = computeConsumptionData(
Expand Down Expand Up @@ -163,14 +162,14 @@ class HuiEnergyDistrubutionCard
}
let batteryFromGrid: null | number = null;
let batteryToGrid: null | number = null;
if (hasBattery) {
if (hasBattery && hasGrid) {
batteryToGrid = consumption.total.battery_to_grid;
batteryFromGrid = consumption.total.grid_to_battery;
}

let solarToBattery: null | number = null;
let solarToGrid: null | number = null;
if (hasSolarProduction) {
if (hasSolarProduction && hasGrid) {
solarToGrid = consumption.total.solar_to_grid;
}
if (hasSolarProduction && hasBattery) {
Expand All @@ -182,7 +181,10 @@ class HuiEnergyDistrubutionCard
batteryConsumption = Math.max(consumption.total.used_battery, 0);
}

const gridConsumption = Math.max(consumption.total.used_grid, 0);
let gridConsumption: number | null = null;
if (hasGrid) {
gridConsumption = Math.max(consumption.total.used_grid, 0);
}

const totalHomeConsumption = Math.max(0, consumption.total.used_total);

Expand All @@ -206,7 +208,11 @@ class HuiEnergyDistrubutionCard
// This fallback is used in the demo
let electricityMapUrl = "https://app.electricitymap.org";

if (this._data.co2SignalEntity && this._data.fossilEnergyConsumption) {
if (
hasGrid &&
this._data.co2SignalEntity &&
this._data.fossilEnergyConsumption
) {
// Calculate high carbon consumption
const highCarbonEnergy = Object.values(
this._data.fossilEnergyConsumption
Expand All @@ -225,7 +231,7 @@ class HuiEnergyDistrubutionCard
if (gridConsumption !== totalFromGrid) {
// Only get the part that was used for consumption and not the battery
highCarbonConsumption =
highCarbonEnergy * (gridConsumption / totalFromGrid);
highCarbonEnergy * (gridConsumption! / totalFromGrid);
} else {
highCarbonConsumption = highCarbonEnergy;
}
Expand All @@ -242,7 +248,7 @@ class HuiEnergyDistrubutionCard
}

const totalLines =
gridConsumption +
(gridConsumption || 0) +
(solarConsumption || 0) +
(solarToGrid || 0) +
(solarToBattery || 0) +
Expand Down Expand Up @@ -378,41 +384,43 @@ class HuiEnergyDistrubutionCard
</div>`
: ""}
<div class="row">
<div class="circle-container grid">
<div class="circle">
<ha-svg-icon .path=${mdiTransmissionTower}></ha-svg-icon>
${returnedToGrid !== null
? html`<span class="return">
<ha-svg-icon
class="small"
.path=${mdiArrowLeft}
></ha-svg-icon
>${formatConsumptionShort(
${hasGrid
? html`<div class="circle-container grid">
<div class="circle">
<ha-svg-icon .path=${mdiTransmissionTower}></ha-svg-icon>
${returnedToGrid !== null
? html`<span class="return">
<ha-svg-icon
class="small"
.path=${mdiArrowLeft}
></ha-svg-icon
>${formatConsumptionShort(
this.hass,
returnedToGrid,
"kWh"
)}
</span>`
: ""}
<span class="consumption">
${hasReturnToGrid
? html`<ha-svg-icon
class="small"
.path=${mdiArrowRight}
></ha-svg-icon>`
: ""}${formatConsumptionShort(
this.hass,
returnedToGrid,
totalFromGrid,
"kWh"
)}
</span>`
: ""}
<span class="consumption">
${hasReturnToGrid
? html`<ha-svg-icon
class="small"
.path=${mdiArrowRight}
></ha-svg-icon>`
: ""}${formatConsumptionShort(
this.hass,
totalFromGrid,
"kWh"
)}
</span>
</div>
<span class="label"
>${this.hass.localize(
"ui.panel.lovelace.cards.energy.energy_distribution.grid"
)}</span
>
</div>
</span>
</div>
<span class="label"
>${this.hass.localize(
"ui.panel.lovelace.cards.energy.energy_distribution.grid"
)}</span
>
</div> `
: html`<div class="grid-spacer"></div>`}
<div class="circle-container home">
<div
class="circle ${classMap({
Expand Down Expand Up @@ -480,22 +488,27 @@ class HuiEnergyDistrubutionCard
shape-rendering="geometricPrecision"
/>`
: ""}
<circle
${hasGrid
? svg`<circle
class="grid"
cx="40"
cy="40"
r="38"
stroke-dasharray="${homeHighCarbonCircumference ??
CIRCLE_CIRCUMFERENCE -
homeSolarCircumference! -
(homeBatteryCircumference ||
0)} ${homeHighCarbonCircumference !== undefined
? CIRCLE_CIRCUMFERENCE - homeHighCarbonCircumference
: homeSolarCircumference! +
(homeBatteryCircumference || 0)}"
stroke-dasharray="${
homeHighCarbonCircumference ??
CIRCLE_CIRCUMFERENCE -
homeSolarCircumference! -
(homeBatteryCircumference || 0)
} ${
homeHighCarbonCircumference !== undefined
? CIRCLE_CIRCUMFERENCE - homeHighCarbonCircumference
: homeSolarCircumference! +
(homeBatteryCircumference || 0)
}"
stroke-dashoffset="0"
shape-rendering="geometricPrecision"
/>
/>`
: nothing}
</svg>`
: ""}
</div>
Expand Down Expand Up @@ -619,15 +632,19 @@ class HuiEnergyDistrubutionCard
d="M55,100 v-15 c0,-35 10,-30 30,-30 h20"
vector-effect="non-scaling-stroke"
></path>
<path
id="battery-grid"
class=${classMap({
"battery-from-grid": Boolean(batteryFromGrid),
"battery-to-grid": Boolean(batteryToGrid),
})}
d="M45,100 v-15 c0,-35 -10,-30 -30,-30 h-20"
vector-effect="non-scaling-stroke"
></path>
${
hasGrid
? svg`<path
id="battery-grid"
class=${classMap({
"battery-from-grid": Boolean(batteryFromGrid),
"battery-to-grid": Boolean(batteryToGrid),
})}
d="M45,100 v-15 c0,-35 -10,-30 -30,-30 h-20"
vector-effect="non-scaling-stroke"
></path>`
: nothing
}
`
: ""}
${hasBattery && hasSolarProduction
Expand All @@ -638,12 +655,14 @@ class HuiEnergyDistrubutionCard
vector-effect="non-scaling-stroke"
></path>`
: ""}
<path
class="grid"
id="grid"
d="M0,${hasBattery ? 50 : hasSolarProduction ? 56 : 53} H100"
vector-effect="non-scaling-stroke"
></path>
${hasGrid
? svg`<path
class="grid"
id="grid"
d="M0,${hasBattery ? 50 : hasSolarProduction ? 56 : 53} H100"
vector-effect="non-scaling-stroke"
></path>`
: nothing}
${solarToGrid && this._animate
? svg`<circle
r="1"
Expand Down Expand Up @@ -839,6 +858,10 @@ class HuiEnergyDistrubutionCard
.spacer {
width: 84px;
}
.grid-spacer {
width: 84px;
height: 100px;
}
.circle {
width: 80px;
height: 80px;
Expand Down
Loading