diff --git a/src/panels/lovelace/cards/hui-statistic-card.ts b/src/panels/lovelace/cards/hui-statistic-card.ts index 7fafcf8a7db3..eebe867bbf0d 100644 --- a/src/panels/lovelace/cards/hui-statistic-card.ts +++ b/src/panels/lovelace/cards/hui-statistic-card.ts @@ -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 { @@ -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; diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts index 51a1a7f0c011..b932d8da37db 100644 --- a/src/panels/lovelace/cards/types.ts +++ b/src/panels/lovelace/cards/types.ts @@ -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; } diff --git a/src/panels/lovelace/editor/config-elements/hui-statistic-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-statistic-card-editor.ts index 4702abe33810..b44bb8cca11f 100644 --- a/src/panels/lovelace/editor/config-elements/hui-statistic-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-statistic-card-editor.ts @@ -32,6 +32,7 @@ const cardConfigStruct = assign( period: optional(any()), theme: optional(string()), footer: optional(headerFooterConfigStructs), + collection_key: optional(string()), }) );