From 72403f42766d6e69cae394fb1a3de1c1a94e4a8f Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 11 May 2023 10:17:12 +0200 Subject: [PATCH] Remove calculation of change from frontend (#16477) --- src/components/chart/statistics-chart.ts | 28 +-------- src/data/energy.ts | 58 ++++--------------- src/data/recorder.ts | 28 +++++---- .../energy/hui-energy-devices-graph-card.ts | 39 ++----------- .../cards/energy/hui-energy-gas-graph-card.ts | 11 +--- .../energy/hui-energy-solar-graph-card.ts | 11 +--- .../energy/hui-energy-usage-graph-card.ts | 10 +--- .../energy/hui-energy-water-graph-card.ts | 11 +--- .../cards/hui-statistics-graph-card.ts | 11 ++-- src/panels/lovelace/cards/types.ts | 5 +- .../hui-statistics-graph-card-editor.ts | 13 ++--- 11 files changed, 55 insertions(+), 170 deletions(-) diff --git a/src/components/chart/statistics-chart.ts b/src/components/chart/statistics-chart.ts index 1374d9dbf6..014e658417 100644 --- a/src/components/chart/statistics-chart.ts +++ b/src/components/chart/statistics-chart.ts @@ -32,12 +32,7 @@ import { import type { HomeAssistant } from "../../types"; import "./ha-chart-base"; -export type ExtendedStatisticType = StatisticType | "change"; - -export const supportedStatTypeMap: Record< - ExtendedStatisticType, - StatisticType -> = { +export const supportedStatTypeMap: Record = { mean: "mean", min: "min", max: "max", @@ -46,15 +41,6 @@ export const supportedStatTypeMap: Record< change: "sum", }; -export const statTypeMap: Record = { - mean: "mean", - min: "min", - max: "max", - sum: "sum", - state: "state", - change: "sum", -}; - @customElement("statistics-chart") class StatisticsChart extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -72,7 +58,7 @@ class StatisticsChart extends LitElement { @property({ attribute: false }) public endTime?: Date; - @property({ type: Array }) public statTypes: Array = [ + @property({ type: Array }) public statTypes: Array = [ "sum", "min", "mean", @@ -358,7 +344,7 @@ class StatisticsChart extends LitElement { : this.statTypes; sortedTypes.forEach((type) => { - if (statisticsHaveType(stats, statTypeMap[type])) { + if (statisticsHaveType(stats, type)) { const band = drawBands && (type === "min" || type === "max"); statTypes.push(type); statDataSets.push({ @@ -391,7 +377,6 @@ class StatisticsChart extends LitElement { let prevDate: Date | null = null; // Process chart data. let firstSum: number | null | undefined = null; - let prevSum: number | null | undefined = null; stats.forEach((stat) => { const startDate = new Date(stat.start); if (prevDate === startDate) { @@ -408,13 +393,6 @@ class StatisticsChart extends LitElement { } else { val = (stat.sum || 0) - firstSum; } - } else if (type === "change") { - if (prevSum === null || prevSum === undefined) { - prevSum = stat.sum; - return; - } - val = (stat.sum || 0) - prevSum; - prevSum = stat.sum; } else { val = stat[type]; } diff --git a/src/data/energy.ts b/src/data/energy.ts index d253d63d0d..a36500d1b1 100644 --- a/src/data/energy.ts +++ b/src/data/energy.ts @@ -1,8 +1,6 @@ import { - addDays, addHours, addMilliseconds, - addMonths, differenceInDays, endOfToday, endOfYesterday, @@ -389,9 +387,6 @@ const getEnergyData = async ( const period = dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour"; - // Subtract 1 hour from start to get starting point data - const startMinHour = addHours(start, -1); - const lengthUnit = hass.config.unit_system.length || ""; const energyUnits: StatisticsUnitConfiguration = { energy: "kWh", @@ -402,26 +397,14 @@ const getEnergyData = async ( }; const _energyStats: Statistics | Promise = energyStatIds.length - ? fetchStatistics( - hass!, - startMinHour, - end, - energyStatIds, - period, - energyUnits, - ["sum"] - ) + ? fetchStatistics(hass!, start, end, energyStatIds, period, energyUnits, [ + "change", + ]) : {}; const _waterStats: Statistics | Promise = waterStatIds.length - ? fetchStatistics( - hass!, - startMinHour, - end, - waterStatIds, - period, - waterUnits, - ["sum"] - ) + ? fetchStatistics(hass!, start, end, waterStatIds, period, waterUnits, [ + "change", + ]) : {}; let statsCompare; @@ -431,35 +414,27 @@ const getEnergyData = async ( let _waterStatsCompare: Statistics | Promise = {}; if (compare) { - if (dayDifference > 27 && dayDifference < 32) { - // When comparing a month, we want to start at the begining of the month - startCompare = addMonths(start, -1); - } else { - startCompare = addDays(start, (dayDifference + 1) * -1); - } - - const compareStartMinHour = addHours(startCompare, -1); endCompare = addMilliseconds(start, -1); if (energyStatIds.length) { _energyStatsCompare = fetchStatistics( hass!, - compareStartMinHour, + start, endCompare, energyStatIds, period, energyUnits, - ["sum"] + ["change"] ); } if (waterStatIds.length) { _waterStatsCompare = fetchStatistics( hass!, - compareStartMinHour, + start, endCompare, waterStatIds, period, waterUnits, - ["sum"] + ["change"] ); } } @@ -522,19 +497,6 @@ const getEnergyData = async ( }); } - Object.values(stats).forEach((stat) => { - // if the start of the first value is after the requested period, we have the first data point, and should add a zero point - if (stat.length && new Date(stat[0].start) > startMinHour) { - stat.unshift({ - ...stat[0], - start: startMinHour.getTime(), - end: startMinHour.getTime(), - sum: 0, - state: 0, - }); - } - }); - const data: EnergyData = { start, end, diff --git a/src/data/recorder.ts b/src/data/recorder.ts index 7d93854db5..ebcaa744ba 100644 --- a/src/data/recorder.ts +++ b/src/data/recorder.ts @@ -2,7 +2,7 @@ import { computeStateName } from "../common/entity/compute_state_name"; import { HaDurationData } from "../components/ha-duration-input"; import { HomeAssistant } from "../types"; -export type StatisticType = "state" | "sum" | "min" | "max" | "mean"; +export type StatisticType = "change" | "state" | "sum" | "min" | "max" | "mean"; export interface Statistics { [statisticId: string]: StatisticValue[]; @@ -11,6 +11,7 @@ export interface Statistics { export interface StatisticValue { start: number; end: number; + change?: number | null; last_reset?: number | null; max?: number | null; mean?: number | null; @@ -91,6 +92,7 @@ export interface StatisticsUnitConfiguration { } const statisticTypes = [ + "change", "last_reset", "max", "mean", @@ -196,18 +198,24 @@ export const clearStatistics = (hass: HomeAssistant, statistic_ids: string[]) => export const calculateStatisticSumGrowth = ( values: StatisticValue[] ): number | null => { - if (!values || values.length < 2) { + let growth: number | null = null; + + if (!values) { return null; } - const endSum = values[values.length - 1].sum; - if (endSum === null || endSum === undefined) { - return null; + + for (const value of values) { + if (value.change === null || value.change === undefined) { + continue; + } + if (growth === null) { + growth = value.change; + } else { + growth += value.change; + } } - const startSum = values[0].sum; - if (startSum === null || startSum === undefined) { - return endSum; - } - return endSum - startSum; + + return growth; }; export const calculateStatisticsSumGrowth = ( diff --git a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts index 2e302e01b6..cdf7431129 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-devices-graph-card.ts @@ -6,7 +6,7 @@ import { ScatterDataPoint, } from "chart.js"; import { getRelativePosition } from "chart.js/helpers"; -import { addHours, differenceInDays } from "date-fns/esm"; +import { differenceInDays } from "date-fns/esm"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property, query, state } from "lit/decorators"; @@ -181,8 +181,6 @@ export class HuiEnergyDevicesGraphCard const period = dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour"; - const startMinHour = addHours(energyData.start, -1); - const lengthUnit = this.hass.config.unit_system.length || ""; const units: StatisticsUnitConfiguration = { energy: "kWh", @@ -191,53 +189,26 @@ export class HuiEnergyDevicesGraphCard const data = await fetchStatistics( this.hass, - startMinHour, + energyData.start, energyData.end, devices, period, units, - ["sum"] + ["change"] ); - Object.values(data).forEach((stat) => { - // if the start of the first value is after the requested period, we have the first data point, and should add a zero point - if (stat.length && new Date(stat[0].start) > startMinHour) { - stat.unshift({ - ...stat[0], - start: startMinHour.getTime(), - end: startMinHour.getTime(), - sum: 0, - state: 0, - }); - } - }); - let compareData: Statistics | undefined; if (energyData.startCompare && energyData.endCompare) { - const startCompareMinHour = addHours(energyData.startCompare, -1); compareData = await fetchStatistics( this.hass, - startCompareMinHour, + energyData.startCompare, energyData.endCompare, devices, period, units, - ["sum"] + ["change"] ); - - Object.values(compareData).forEach((stat) => { - // if the start of the first value is after the requested period, we have the first data point, and should add a zero point - if (stat.length && new Date(stat[0].start) > startMinHour) { - stat.unshift({ - ...stat[0], - start: startCompareMinHour.getTime(), - end: startCompareMinHour.getTime(), - sum: 0, - state: 0, - }); - } - }); } const chartData: Array>["data"]> = diff --git a/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts index b081a62ff0..8fa32d49b1 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-gas-graph-card.ts @@ -345,7 +345,6 @@ export class HuiEnergyGasGraphCard ? rgb2hex(lab2rgb(modifiedColor)) : gasColor; - let prevValue: number | null = null; let prevStart: number | null = null; const gasConsumptionData: ScatterDataPoint[] = []; @@ -355,24 +354,18 @@ export class HuiEnergyGasGraphCard const stats = statistics[source.stat_energy_from]; for (const point of stats) { - if (point.sum === null || point.sum === undefined) { - continue; - } - if (prevValue === null || prevValue === undefined) { - prevValue = point.sum; + if (point.change === null || point.change === undefined) { continue; } if (prevStart === point.start) { continue; } - const value = point.sum - prevValue; const date = new Date(point.start); gasConsumptionData.push({ x: date.getTime(), - y: value, + y: point.change, }); prevStart = point.start; - prevValue = point.sum; } } diff --git a/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts index df3ad940c3..6c693b4b46 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-solar-graph-card.ts @@ -365,7 +365,6 @@ export class HuiEnergySolarGraphCard ? rgb2hex(lab2rgb(modifiedColor)) : solarColor; - let prevValue: number | null = null; let prevStart: number | null = null; const solarProductionData: ScatterDataPoint[] = []; @@ -375,24 +374,18 @@ export class HuiEnergySolarGraphCard const stats = statistics[source.stat_energy_from]; for (const point of stats) { - if (point.sum === null || point.sum === undefined) { - continue; - } - if (prevValue === null || prevValue === undefined) { - prevValue = point.sum; + if (point.change === null || point.change === undefined) { continue; } if (prevStart === point.start) { continue; } - const value = point.sum - prevValue; const date = new Date(point.start); solarProductionData.push({ x: date.getTime(), - y: value, + y: point.change, }); prevStart = point.start; - prevValue = point.sum; } } diff --git a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts index fc1ff68cf3..693f5deb83 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-usage-graph-card.ts @@ -478,16 +478,11 @@ export class HuiEnergyUsageGraphCard } const set = {}; - let prevValue: number; stats.forEach((stat) => { - if (stat.sum === null || stat.sum === undefined) { + if (stat.change === null || stat.change === undefined) { return; } - if (prevValue === undefined) { - prevValue = stat.sum; - return; - } - const val = stat.sum - prevValue; + const val = stat.change; // Get total of solar and to grid to calculate the solar energy used if (sum) { totalStats[stat.start] = @@ -496,7 +491,6 @@ export class HuiEnergyUsageGraphCard if (add && !(stat.start in set)) { set[stat.start] = val; } - prevValue = stat.sum; }); sets[id] = set; }); diff --git a/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts b/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts index 08370783cf..709921d45c 100644 --- a/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts +++ b/src/panels/lovelace/cards/energy/hui-energy-water-graph-card.ts @@ -343,7 +343,6 @@ export class HuiEnergyWaterGraphCard ? rgb2hex(lab2rgb(modifiedColor)) : waterColor; - let prevValue: number | null = null; let prevStart: number | null = null; const waterConsumptionData: ScatterDataPoint[] = []; @@ -353,24 +352,18 @@ export class HuiEnergyWaterGraphCard const stats = statistics[source.stat_energy_from]; for (const point of stats) { - if (point.sum === null || point.sum === undefined) { - continue; - } - if (prevValue === null || prevValue === undefined) { - prevValue = point.sum; + if (point.change === null || point.change === undefined) { continue; } if (prevStart === point.start) { continue; } - const value = point.sum - prevValue; const date = new Date(point.start); waterConsumptionData.push({ x: date.getTime(), - y: value, + y: point.change, }); prevStart = point.start; - prevValue = point.sum; } } diff --git a/src/panels/lovelace/cards/hui-statistics-graph-card.ts b/src/panels/lovelace/cards/hui-statistics-graph-card.ts index 49a3428adc..59c16a0404 100644 --- a/src/panels/lovelace/cards/hui-statistics-graph-card.ts +++ b/src/panels/lovelace/cards/hui-statistics-graph-card.ts @@ -9,10 +9,6 @@ import { } from "lit"; import { customElement, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; -import { - ExtendedStatisticType, - statTypeMap, -} from "../../../components/chart/statistics-chart"; import "../../../components/ha-card"; import { fetchStatistics, @@ -20,6 +16,7 @@ import { getStatisticMetadata, Statistics, StatisticsMetaData, + StatisticType, } from "../../../data/recorder"; import { HomeAssistant } from "../../../types"; import { findEntities } from "../common/find-entities"; @@ -74,7 +71,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard { private _interval?: number; - private _statTypes?: Array; + private _statTypes?: Array; public disconnectedCallback() { super.disconnectedCallback(); @@ -124,7 +121,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard { if (typeof config.stat_types === "string") { this._statTypes = [config.stat_types]; } else if (!config.stat_types) { - this._statTypes = ["state", "sum", "min", "max", "mean"]; + this._statTypes = ["change", "state", "sum", "min", "max", "mean"]; } else { this._statTypes = config.stat_types; } @@ -261,7 +258,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard { this._entities, this._config!.period, unitconfig, - this._statTypes?.map((stat_type) => statTypeMap[stat_type]) + this._statTypes ); } catch (err) { this._statistics = undefined; diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts index e82f1eeea5..0e65d9a46a 100644 --- a/src/panels/lovelace/cards/types.ts +++ b/src/panels/lovelace/cards/types.ts @@ -1,4 +1,4 @@ -import { Statistic } from "../../../data/recorder"; +import { Statistic, StatisticType } from "../../../data/recorder"; import { ActionConfig, LovelaceCardConfig } from "../../../data/lovelace"; import { FullCalendarView, TranslationDict } from "../../../types"; import { Condition } from "../common/validate-condition"; @@ -10,7 +10,6 @@ import { LovelaceRowConfig, } from "../entity-rows/types"; import { LovelaceHeaderFooterConfig } from "../header-footer/types"; -import { ExtendedStatisticType } from "../../../components/chart/statistics-chart"; import { HaDurationData } from "../../../components/ha-duration-input"; import { LovelaceTileFeatureConfig } from "../tile-features/types"; @@ -310,7 +309,7 @@ export interface StatisticsGraphCardConfig extends LovelaceCardConfig { unit?: string; days_to_show?: number; period?: "5minute" | "hour" | "day" | "month"; - stat_types?: ExtendedStatisticType | ExtendedStatisticType[]; + stat_types?: StatisticType | StatisticType[]; chart_type?: "line" | "bar"; hide_legend?: boolean; } diff --git a/src/panels/lovelace/editor/config-elements/hui-statistics-graph-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-statistics-graph-card-editor.ts index 689985508e..e16a629b8f 100644 --- a/src/panels/lovelace/editor/config-elements/hui-statistics-graph-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-statistics-graph-card-editor.ts @@ -24,11 +24,7 @@ import { ensureArray } from "../../../../common/array/ensure-array"; import { fireEvent } from "../../../../common/dom/fire_event"; import type { LocalizeFunc } from "../../../../common/translations/localize"; import { deepEqual } from "../../../../common/util/deep-equal"; -import { - ExtendedStatisticType, - statTypeMap, - supportedStatTypeMap, -} from "../../../../components/chart/statistics-chart"; +import { supportedStatTypeMap } from "../../../../components/chart/statistics-chart"; import "../../../../components/entity/ha-statistics-picker"; import "../../../../components/ha-form/ha-form"; import type { HaFormSchema } from "../../../../components/ha-form/types"; @@ -38,6 +34,7 @@ import { isExternalStatistic, StatisticsMetaData, statisticsMetaHasType, + StatisticType, } from "../../../../data/recorder"; import type { HomeAssistant } from "../../../../types"; import type { StatisticsGraphCardConfig } from "../../cards/types"; @@ -86,7 +83,7 @@ const stat_types = [ "sum", "state", "change", -] as ExtendedStatisticType[]; +] as StatisticType[]; @customElement("hui-statistics-graph-card-editor") export class HuiStatisticsGraphCardEditor @@ -253,7 +250,7 @@ export class HuiStatisticsGraphCardEditor (stat_type) => stat_type !== "change" && this._metaDatas?.every((metaData) => - statisticsMetaHasType(metaData, statTypeMap[stat_type]) + statisticsMetaHasType(metaData, stat_type) ) ); const data = { @@ -324,7 +321,7 @@ export class HuiStatisticsGraphCardEditor if (config.stat_types && config.entities.length) { config.stat_types = ensureArray(config.stat_types).filter((stat_type) => metadata!.every((metaData) => - statisticsMetaHasType(metaData, statTypeMap[stat_type]) + statisticsMetaHasType(metaData, stat_type) ) ); if (!config.stat_types.length) {