1
0
mirror of https://github.com/home-assistant/frontend.git synced 2026-02-15 07:25:54 +00:00

Smarter floor/area grouping for energy sankey cards

Instead of hiding floors and areas whenever any device has an upstream
parent (included_in_stat), check whether each parent shares the same
area as its children. Only disable grouping when a mismatch is found.
This commit is contained in:
Petar Petrov
2026-02-12 10:02:23 +02:00
parent 432e8fc0d7
commit 36c54a30ea
5 changed files with 84 additions and 27 deletions

View File

@@ -38,6 +38,18 @@ export const getEntityContext = (
return getEntityEntryContext(entry, entities, devices, areas, floors);
};
export const getEntityAreaId = (
entityId: string,
entities: HomeAssistant["entities"],
devices: HomeAssistant["devices"]
): string | undefined => {
const entry = entities[entityId];
if (!entry) return undefined;
const deviceId = entry.device_id;
const device = deviceId ? devices[deviceId] : undefined;
return entry.area_id || device?.area_id || undefined;
};
export const getEntityEntryContext = (
entry:
| EntityRegistryDisplayEntry

View File

@@ -2,10 +2,11 @@ import { ReactiveElement } from "lit";
import { customElement } from "lit/decorators";
import type { GridSourceTypeEnergyPreference } from "../../../data/energy";
import { getEnergyDataCollection } from "../../../data/energy";
import type { HomeAssistant } from "../../../types";
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../types";
import { DEFAULT_ENERGY_COLLECTION_KEY } from "../ha-panel-energy";
import { shouldShowFloorsAndAreas } from "./show-floors-and-areas";
@customElement("energy-view-strategy")
export class EnergyViewStrategy extends ReactiveElement {
@@ -49,10 +50,6 @@ export class EnergyViewStrategy extends ReactiveElement {
const hasBattery = prefs.energy_sources.some(
(source) => source.type === "battery"
);
const showFloorsNAreas = !prefs.device_consumption.some(
(d) => d.included_in_stat
);
view.cards!.push({
type: "energy-compare",
collection_key: "energy_dashboard",
@@ -135,6 +132,11 @@ export class EnergyViewStrategy extends ReactiveElement {
// Only include if we have at least 1 device in the config.
if (prefs.device_consumption.length) {
const showFloorsAndAreas = shouldShowFloorsAndAreas(
prefs.device_consumption,
hass,
(d) => d.stat_consumption
);
view.cards!.push({
title: hass.localize(
"ui.panel.energy.cards.energy_devices_detail_graph_title"
@@ -153,8 +155,8 @@ export class EnergyViewStrategy extends ReactiveElement {
title: hass.localize("ui.panel.energy.cards.energy_sankey_title"),
type: "energy-sankey",
collection_key: "energy_dashboard",
group_by_floor: showFloorsNAreas,
group_by_area: showFloorsNAreas,
group_by_floor: showFloorsAndAreas,
group_by_area: showFloorsAndAreas,
});
}

View File

@@ -1,11 +1,12 @@
import { ReactiveElement } from "lit";
import { customElement } from "lit/decorators";
import { getEnergyDataCollection } from "../../../data/energy";
import type { HomeAssistant } from "../../../types";
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
import { DEFAULT_ENERGY_COLLECTION_KEY } from "../ha-panel-energy";
import type { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../types";
import { DEFAULT_ENERGY_COLLECTION_KEY } from "../ha-panel-energy";
import { shouldShowFloorsAndAreas } from "./show-floors-and-areas";
@customElement("power-view-strategy")
export class PowerViewStrategy extends ReactiveElement {
@@ -56,15 +57,17 @@ export class PowerViewStrategy extends ReactiveElement {
}
if (hasPowerDevices) {
const showFloorsNAreas = !prefs.device_consumption.some(
(d) => d.included_in_stat
const showFloorsAndAreas = shouldShowFloorsAndAreas(
prefs.device_consumption,
hass,
(d) => d.stat_rate
);
section.cards!.push({
title: hass.localize("ui.panel.energy.cards.power_sankey_title"),
type: "power-sankey",
collection_key: collectionKey,
group_by_floor: showFloorsNAreas,
group_by_area: showFloorsNAreas,
group_by_floor: showFloorsAndAreas,
group_by_area: showFloorsAndAreas,
grid_options: {
columns: 36,
},

View File

@@ -0,0 +1,40 @@
import type { DeviceConsumptionEnergyPreference } from "../../../data/energy";
import type { HomeAssistant } from "../../../types";
import { getEntityAreaId } from "../../../common/entity/context/get_entity_context";
export function shouldShowFloorsAndAreas(
devices: DeviceConsumptionEnergyPreference[],
hass: HomeAssistant,
getEntityId: (device: DeviceConsumptionEnergyPreference) => string | undefined
): boolean {
if (!devices.some((d) => d.included_in_stat)) return true;
const deviceMap = new Map(devices.map((d) => [d.stat_consumption, d]));
for (const device of devices) {
if (!device.included_in_stat) continue;
const parent = deviceMap.get(device.included_in_stat);
if (!parent) continue;
const childEntityId = getEntityId(device);
const parentEntityId = getEntityId(parent);
if (!childEntityId || !parentEntityId) continue;
const childArea = getEntityAreaId(
childEntityId,
hass.entities,
hass.devices
);
const parentArea = getEntityAreaId(
parentEntityId,
hass.entities,
hass.devices
);
if (childArea !== parentArea) return false;
}
return true;
}

View File

@@ -1,11 +1,12 @@
import { ReactiveElement } from "lit";
import { customElement } from "lit/decorators";
import { getEnergyDataCollection } from "../../../data/energy";
import type { HomeAssistant } from "../../../types";
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
import { DEFAULT_ENERGY_COLLECTION_KEY } from "../ha-panel-energy";
import type { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../types";
import { DEFAULT_ENERGY_COLLECTION_KEY } from "../ha-panel-energy";
import { shouldShowFloorsAndAreas } from "./show-floors-and-areas";
@customElement("water-view-strategy")
export class WaterViewStrategy extends ReactiveElement {
@@ -52,9 +53,6 @@ export class WaterViewStrategy extends ReactiveElement {
type: "energy-water-graph",
collection_key: collectionKey,
});
}
if (hasWaterSources) {
section.cards!.push({
title: hass.localize(
"ui.panel.energy.cards.energy_sources_table_title"
@@ -67,15 +65,17 @@ export class WaterViewStrategy extends ReactiveElement {
// Only include if we have at least 1 water device in the config.
if (hasWaterDevices) {
const showFloorsNAreas = !prefs.device_consumption_water.some(
(d) => d.included_in_stat
const showFloorsAndAreas = shouldShowFloorsAndAreas(
prefs.device_consumption_water,
hass,
(d) => d.stat_consumption
);
section.cards!.push({
title: hass.localize("ui.panel.energy.cards.water_sankey_title"),
type: "water-sankey",
collection_key: collectionKey,
group_by_floor: showFloorsNAreas,
group_by_area: showFloorsNAreas,
group_by_floor: showFloorsAndAreas,
group_by_area: showFloorsAndAreas,
});
}