Enable Statistics Graph card to integrate with Energy Dashboard (V2) (#23478)

* Simplify date subtraction

* Enable Statistics Graph card to integrate with Energy Dashboard

Adds boolean option `energy_date_selection` to Statistics Graph card. If
true, the graph will set its time range to that specified by an Energy
Date Picker card on the same dashboard, similar to the plots on the
Energy Dashboard.

* Revert UI addition

PR reviewer suggested it was too confusing, especially without
dynamically hiding the overridden days_to_show option.

* Remove boolean param energy_date_selection

and instead activate when collection_key is specified

* Revert "Remove boolean param energy_date_selection"

This reverts commit 95cebdbbe35dcb04339b940e929fe5db0094721a.

* Don't assume !20903 has merged

* updates

* refresh when collection_key changes

---------

Co-authored-by: Andrew Reiter <reiterandrew@gmail.com>
This commit is contained in:
karwosts 2025-01-08 05:36:19 -08:00 committed by GitHub
parent 221b3932ed
commit b1acf9a057
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 93 additions and 19 deletions

View File

@ -33,6 +33,12 @@ export function getSuggestedMax(dayDifference: number, end: Date): number {
return suggestedMax.getTime();
}
export function getSuggestedPeriod(
dayDifference: number
): "month" | "day" | "hour" {
return dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour";
}
export function getCommonOptions(
start: Date,
end: Date,
@ -91,8 +97,7 @@ export function getCommonOptions(
: dayDifference > 0
? "datetime"
: "hour",
minUnit:
dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour",
minUnit: getSuggestedPeriod(dayDifference),
},
},
y: {

View File

@ -1,9 +1,12 @@
import type { HassEntity } from "home-assistant-js-websocket";
import type { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
import { subHours, differenceInDays } from "date-fns";
import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import "../../../components/ha-card";
import { getEnergyDataCollection } from "../../../data/energy";
import { getSuggestedPeriod } from "./energy/common/energy-chart-options";
import type {
Statistics,
StatisticsMetaData,
@ -69,8 +72,15 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
private _statTypes?: Array<StatisticType>;
private _energySub?: UnsubscribeFunc;
@state() private _energyStart?: Date;
@state() private _energyEnd?: Date;
public disconnectedCallback() {
super.disconnectedCallback();
this._unsubscribeEnergy();
if (this._interval) {
clearInterval(this._interval);
this._interval = undefined;
@ -82,7 +92,32 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
if (!this.hasUpdated) {
return;
}
this._setFetchStatisticsTimer();
if (this._config?.energy_date_selection) {
this._subscribeEnergy();
} else {
this._setFetchStatisticsTimer();
}
}
private _subscribeEnergy() {
if (!this._energySub) {
this._energySub = getEnergyDataCollection(this.hass!, {
key: this._config?.collection_key,
}).subscribe((data) => {
this._energyStart = data.start;
this._energyEnd = data.end;
this._getStatistics();
});
}
}
private _unsubscribeEnergy() {
if (this._energySub) {
this._energySub();
this._energySub = undefined;
}
this._energyStart = undefined;
this._energyEnd = undefined;
}
public getCardSize(): number {
@ -150,6 +185,27 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
| StatisticsGraphCardConfig
| undefined;
if (this.hass) {
if (this._config.energy_date_selection && !this._energySub) {
this._subscribeEnergy();
return;
}
if (!this._config.energy_date_selection && this._energySub) {
this._unsubscribeEnergy();
this._setFetchStatisticsTimer();
return;
}
if (
this._config.energy_date_selection &&
this._energySub &&
changedProps.has("_config") &&
oldConfig?.collection_key !== this._config.collection_key
) {
this._unsubscribeEnergy();
this._subscribeEnergy();
}
}
if (
changedProps.has("_config") &&
oldConfig?.entities !== this._config.entities
@ -175,9 +231,22 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
this._getStatistics();
// statistics are created every hour
clearInterval(this._interval);
this._interval = window.setInterval(
() => this._getStatistics(),
this._intervalTimeout
if (!this._config?.energy_date_selection) {
this._interval = window.setInterval(
() => this._getStatistics(),
this._intervalTimeout
);
}
}
private get _period() {
return (
this._config?.period ??
(this._energyStart && this._energyEnd
? getSuggestedPeriod(
differenceInDays(this._energyEnd, this._energyStart)
)
: undefined)
);
}
@ -198,7 +267,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
.isLoadingData=${!this._statistics}
.statisticsData=${this._statistics}
.metadata=${this._metadata}
.period=${this._config.period}
.period=${this._period}
.chartType=${this._config.chart_type || "line"}
.statTypes=${this._statTypes!}
.names=${this._names}
@ -231,14 +300,13 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
}
private async _getStatistics(): Promise<void> {
const startDate = new Date();
startDate.setTime(
startDate.getTime() -
1000 *
60 *
60 *
(24 * (this._config!.days_to_show || DEFAULT_DAYS_TO_SHOW) + 1)
);
const startDate =
this._energyStart ??
subHours(
new Date(),
24 * (this._config!.days_to_show || DEFAULT_DAYS_TO_SHOW) + 1
);
const endDate = this._energyEnd;
try {
let unitClass;
if (this._config!.unit && this._metadata) {
@ -264,9 +332,9 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
const statistics = await fetchStatistics(
this.hass!,
startDate,
undefined,
endDate,
this._entities,
this._config!.period,
this._period,
unitconfig,
this._statTypes
);

View File

@ -360,7 +360,7 @@ export interface HistoryGraphCardConfig extends LovelaceCardConfig {
split_device_classes?: boolean;
}
export interface StatisticsGraphCardConfig extends LovelaceCardConfig {
export interface StatisticsGraphCardConfig extends EnergyCardBaseConfig {
title?: string;
entities: Array<EntityConfig | string>;
unit?: string;
@ -373,6 +373,7 @@ export interface StatisticsGraphCardConfig extends LovelaceCardConfig {
fit_y_data?: boolean;
hide_legend?: boolean;
logarithmic_scale?: boolean;
energy_date_selection?: boolean;
}
export interface StatisticCardConfig extends LovelaceCardConfig {