Integrate Statistic Card with Energy Date Picker (#23794)

* Support energy-date-selection for statistic card

* reuse period key
This commit is contained in:
karwosts 2025-02-06 22:29:28 -08:00 committed by GitHub
parent af7bb85667
commit d919e8d333
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 109 additions and 15 deletions

View File

@ -1,4 +1,4 @@
import type { HassEntity } from "home-assistant-js-websocket";
import type { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
import type { CSSResultGroup, PropertyValues } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@ -9,6 +9,7 @@ import { formatNumber } from "../../../common/number/format_number";
import "../../../components/ha-alert";
import "../../../components/ha-card";
import "../../../components/ha-state-icon";
import { getEnergyDataCollection } from "../../../data/energy";
import type { StatisticsMetaData } from "../../../data/recorder";
import {
fetchStatistic,
@ -31,6 +32,8 @@ import type {
import type { HuiErrorCard } from "./hui-error-card";
import type { EntityCardConfig, StatisticCardConfig } from "./types";
export const PERIOD_ENERGY = "energy_date_selection";
@customElement("hui-statistic-card")
export class HuiStatisticCard extends LitElement implements LovelaceCard {
public static async getConfigElement(): Promise<LovelaceCardEditor> {
@ -70,15 +73,52 @@ export class HuiStatisticCard extends LitElement implements LovelaceCard {
@state() private _error?: string;
private _energySub?: UnsubscribeFunc;
@state() private _energyStart?: Date;
@state() private _energyEnd?: Date;
private _interval?: number;
private _footerElement?: HuiErrorCard | LovelaceHeaderFooter;
public disconnectedCallback() {
super.disconnectedCallback();
this._unsubscribeEnergy();
clearInterval(this._interval);
}
public connectedCallback() {
super.connectedCallback();
if (this._config?.period === PERIOD_ENERGY) {
this._subscribeEnergy();
} else {
this._setFetchStatisticTimer();
}
}
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._fetchStatistic();
});
}
}
private _unsubscribeEnergy() {
if (this._energySub) {
this._energySub();
this._energySub = undefined;
}
this._energyStart = undefined;
this._energyEnd = undefined;
}
public setConfig(config: StatisticCardConfig): void {
if (!config.entity) {
throw new Error("Entity must be specified");
@ -99,8 +139,6 @@ export class HuiStatisticCard extends LitElement implements LovelaceCard {
this._config = config;
this._error = undefined;
this._fetchStatistic();
this._fetchMetadata();
if (this._config.footer) {
this._footerElement = createHeaderFooterElement(this._config.footer);
@ -174,7 +212,9 @@ export class HuiStatisticCard extends LitElement implements LovelaceCard {
if (
changedProps.has("_value") ||
changedProps.has("_metadata") ||
changedProps.has("_error")
changedProps.has("_error") ||
changedProps.has("_energyStart") ||
changedProps.has("_energyEnd")
) {
return true;
}
@ -184,6 +224,46 @@ export class HuiStatisticCard extends LitElement implements LovelaceCard {
return true;
}
protected willUpdate(changedProps: PropertyValues) {
super.willUpdate(changedProps);
if (!this._config || !changedProps.has("_config")) {
return;
}
const oldConfig = changedProps.get("_config") as
| StatisticCardConfig
| undefined;
if (this.hass) {
if (this._config.period === PERIOD_ENERGY && !this._energySub) {
this._subscribeEnergy();
return;
}
if (this._config.period !== PERIOD_ENERGY && this._energySub) {
this._unsubscribeEnergy();
this._setFetchStatisticTimer();
return;
}
if (
this._config.period === PERIOD_ENERGY &&
this._energySub &&
changedProps.has("_config") &&
oldConfig?.collection_key !== this._config.collection_key
) {
this._unsubscribeEnergy();
this._subscribeEnergy();
}
}
if (
changedProps.has("_config") &&
oldConfig?.entity !== this._config.entity
) {
this._fetchMetadata().then(() => {
this._setFetchStatisticTimer();
});
}
}
protected firstUpdated() {
this._fetchStatistic();
this._fetchMetadata();
@ -210,20 +290,31 @@ export class HuiStatisticCard extends LitElement implements LovelaceCard {
}
}
private _setFetchStatisticTimer() {
this._fetchStatistic();
// statistics are created every hour
clearInterval(this._interval);
if (this._config?.period !== PERIOD_ENERGY) {
this._interval = window.setInterval(
() => this._fetchStatistic(),
5 * 1000 * 60
);
}
}
private async _fetchStatistic() {
if (!this.hass || !this._config) {
return;
}
clearInterval(this._interval);
this._interval = window.setInterval(
() => this._fetchStatistic(),
5 * 1000 * 60
);
try {
const stats = await fetchStatistic(
this.hass,
this._config.entity,
this._config.period
this._energyStart && this._energyEnd
? { fixed_period: { start: this._energyStart, end: this._energyEnd } }
: typeof this._config?.period === "object"
? this._config?.period
: {}
);
this._value = stats[this._config!.stat_type];
this._error = undefined;

View File

@ -379,11 +379,13 @@ export interface StatisticsGraphCardConfig extends EnergyCardBaseConfig {
export interface StatisticCardConfig extends LovelaceCardConfig {
name?: string;
entities: (EntityConfig | string)[];
period: {
fixed_period?: { start: string; end: string };
calendar?: { period: string; offset: number };
rolling_window?: { duration: HaDurationData; offset: HaDurationData };
};
period:
| {
fixed_period?: { start: string; end: string };
calendar?: { period: string; offset: number };
rolling_window?: { duration: HaDurationData; offset: HaDurationData };
}
| "energy_date_selection";
stat_type: keyof Statistic;
theme?: string;
}

View File

@ -32,6 +32,7 @@ const cardConfigStruct = assign(
period: optional(any()),
theme: optional(string()),
footer: optional(headerFooterConfigStructs),
collection_key: optional(string()),
})
);