Don't fetch unneeded statistics from core (#14423)

This commit is contained in:
Erik Montnemery 2022-11-21 16:24:57 +01:00 committed by GitHub
parent 1a68a2f4d7
commit 0bfb2b4a56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 107 additions and 125 deletions

View File

@ -13,7 +13,6 @@ import {
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
const generateMeanStatistics = (
id: string,
start: Date,
end: Date,
period: "5minute" | "hour" | "day" | "month" = "hour",
@ -29,13 +28,12 @@ const generateMeanStatistics = (
const delta = Math.random() * maxDiff;
const mean = lastVal + delta;
statistics.push({
statistic_id: id,
start: currentDate.toISOString(),
end: currentDate.toISOString(),
start: currentDate.getTime(),
end: currentDate.getTime(),
mean,
min: mean - Math.random() * maxDiff,
max: mean + Math.random() * maxDiff,
last_reset: "1970-01-01T00:00:00+00:00",
last_reset: 0,
state: mean,
sum: null,
});
@ -51,7 +49,6 @@ const generateMeanStatistics = (
};
const generateSumStatistics = (
id: string,
start: Date,
end: Date,
period: "5minute" | "hour" | "day" | "month" = "hour",
@ -67,13 +64,12 @@ const generateSumStatistics = (
const add = Math.random() * maxDiff;
sum += add;
statistics.push({
statistic_id: id,
start: currentDate.toISOString(),
end: currentDate.toISOString(),
start: currentDate.getTime(),
end: currentDate.getTime(),
mean: null,
min: null,
max: null,
last_reset: "1970-01-01T00:00:00+00:00",
last_reset: 0,
state: initValue + sum,
sum,
});
@ -88,7 +84,6 @@ const generateSumStatistics = (
};
const generateCurvedStatistics = (
id: string,
start: Date,
end: Date,
_period: "5minute" | "hour" | "day" | "month" = "hour",
@ -108,13 +103,12 @@ const generateCurvedStatistics = (
const add = Math.random() * maxDiff;
sum += i * add;
statistics.push({
statistic_id: id,
start: currentDate.toISOString(),
end: currentDate.toISOString(),
start: currentDate.getTime(),
end: currentDate.getTime(),
mean: null,
min: null,
max: null,
last_reset: "1970-01-01T00:00:00+00:00",
last_reset: 0,
state: initValue + sum,
sum: metered ? sum : null,
});
@ -137,14 +131,13 @@ const statisticsFunctions: Record<
) => StatisticValue[]
> = {
"sensor.energy_consumption_tarif_1": (
id: string,
_id: string,
start: Date,
end: Date,
period = "hour"
) => {
if (period !== "hour") {
return generateSumStatistics(
id,
start,
end,
period,
@ -153,20 +146,12 @@ const statisticsFunctions: Record<
);
}
const morningEnd = new Date(start.getTime() + 10 * 60 * 60 * 1000);
const morningLow = generateSumStatistics(
id,
start,
morningEnd,
period,
0,
0.7
);
const morningLow = generateSumStatistics(start, morningEnd, period, 0, 0.7);
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
const morningFinalVal = morningLow.length
? morningLow[morningLow.length - 1].sum!
: 0;
const empty = generateSumStatistics(
id,
morningEnd,
eveningStart,
period,
@ -174,7 +159,6 @@ const statisticsFunctions: Record<
0
);
const eveningLow = generateSumStatistics(
id,
eveningStart,
end,
period,
@ -184,14 +168,13 @@ const statisticsFunctions: Record<
return [...morningLow, ...empty, ...eveningLow];
},
"sensor.energy_consumption_tarif_2": (
id: string,
_id: string,
start: Date,
end: Date,
period = "hour"
) => {
if (period !== "hour") {
return generateSumStatistics(
id,
start,
end,
period,
@ -202,7 +185,6 @@ const statisticsFunctions: Record<
const morningEnd = new Date(start.getTime() + 9 * 60 * 60 * 1000);
const eveningStart = new Date(start.getTime() + 20 * 60 * 60 * 1000);
const highTarif = generateSumStatistics(
id,
morningEnd,
eveningStart,
period,
@ -212,9 +194,8 @@ const statisticsFunctions: Record<
const highTarifFinalVal = highTarif.length
? highTarif[highTarif.length - 1].sum!
: 0;
const morning = generateSumStatistics(id, start, morningEnd, period, 0, 0);
const morning = generateSumStatistics(start, morningEnd, period, 0, 0);
const evening = generateSumStatistics(
id,
eveningStart,
end,
period,
@ -223,18 +204,17 @@ const statisticsFunctions: Record<
);
return [...morning, ...highTarif, ...evening];
},
"sensor.energy_production_tarif_1": (id, start, end, period = "hour") =>
generateSumStatistics(id, start, end, period, 0, 0),
"sensor.energy_production_tarif_1": (_id, start, end, period = "hour") =>
generateSumStatistics(start, end, period, 0, 0),
"sensor.energy_production_tarif_1_compensation": (
id,
_id,
start,
end,
period = "hour"
) => generateSumStatistics(id, start, end, period, 0, 0),
"sensor.energy_production_tarif_2": (id, start, end, period = "hour") => {
) => generateSumStatistics(start, end, period, 0, 0),
"sensor.energy_production_tarif_2": (_id, start, end, period = "hour") => {
if (period !== "hour") {
return generateSumStatistics(
id,
start,
end,
period,
@ -246,7 +226,6 @@ const statisticsFunctions: Record<
const productionEnd = new Date(start.getTime() + 21 * 60 * 60 * 1000);
const dayEnd = new Date(endOfDay(productionEnd));
const production = generateCurvedStatistics(
id,
productionStart,
productionEnd,
period,
@ -257,16 +236,8 @@ const statisticsFunctions: Record<
const productionFinalVal = production.length
? production[production.length - 1].sum!
: 0;
const morning = generateSumStatistics(
id,
start,
productionStart,
period,
0,
0
);
const morning = generateSumStatistics(start, productionStart, period, 0, 0);
const evening = generateSumStatistics(
id,
productionEnd,
dayEnd,
period,
@ -274,7 +245,6 @@ const statisticsFunctions: Record<
0
);
const rest = generateSumStatistics(
id,
dayEnd,
end,
period,
@ -283,10 +253,9 @@ const statisticsFunctions: Record<
);
return [...morning, ...production, ...evening, ...rest];
},
"sensor.solar_production": (id, start, end, period = "hour") => {
"sensor.solar_production": (_id, start, end, period = "hour") => {
if (period !== "hour") {
return generateSumStatistics(
id,
start,
end,
period,
@ -298,7 +267,6 @@ const statisticsFunctions: Record<
const productionEnd = new Date(start.getTime() + 23 * 60 * 60 * 1000);
const dayEnd = new Date(endOfDay(productionEnd));
const production = generateCurvedStatistics(
id,
productionStart,
productionEnd,
period,
@ -309,16 +277,8 @@ const statisticsFunctions: Record<
const productionFinalVal = production.length
? production[production.length - 1].sum!
: 0;
const morning = generateSumStatistics(
id,
start,
productionStart,
period,
0,
0
);
const morning = generateSumStatistics(start, productionStart, period, 0, 0);
const evening = generateSumStatistics(
id,
productionEnd,
dayEnd,
period,
@ -326,7 +286,6 @@ const statisticsFunctions: Record<
0
);
const rest = generateSumStatistics(
id,
dayEnd,
end,
period,
@ -362,7 +321,6 @@ export const mockRecorder = (mockHass: MockHomeAssistant) => {
statistics[id] =
entityState && "last_reset" in entityState.attributes
? generateSumStatistics(
id,
start,
end,
period,
@ -370,7 +328,6 @@ export const mockRecorder = (mockHass: MockHomeAssistant) => {
state * (state > 80 ? 0.01 : 0.05)
)
: generateMeanStatistics(
id,
start,
end,
period,

View File

@ -233,7 +233,7 @@ class StatisticsChart extends LitElement {
(await this._getStatisticsMetaData(Object.keys(this.statisticsData)));
let colorIndex = 0;
const statisticsData = Object.values(this.statisticsData);
const statisticsData = Object.entries(this.statisticsData);
const totalDataSets: ChartDataset<"line">[] = [];
let endTime: Date;
@ -246,7 +246,7 @@ class StatisticsChart extends LitElement {
// Get the highest date from the last date of each statistic
new Date(
Math.max(
...statisticsData.map((stats) =>
...statisticsData.map(([_, stats]) =>
new Date(stats[stats.length - 1].start).getTime()
)
)
@ -259,20 +259,19 @@ class StatisticsChart extends LitElement {
let unit: string | undefined | null;
const names = this.names || {};
statisticsData.forEach((stats) => {
const firstStat = stats[0];
const meta = statisticsMetaData?.[firstStat.statistic_id];
let name = names[firstStat.statistic_id];
statisticsData.forEach(([statistic_id, stats]) => {
const meta = statisticsMetaData?.[statistic_id];
let name = names[statistic_id];
if (name === undefined) {
name = getStatisticLabel(this.hass, firstStat.statistic_id, meta);
name = getStatisticLabel(this.hass, statistic_id, meta);
}
if (!this.unit) {
if (unit === undefined) {
unit = getDisplayUnit(this.hass, firstStat.statistic_id, meta);
unit = getDisplayUnit(this.hass, statistic_id, meta);
} else if (
unit !== null &&
unit !== getDisplayUnit(this.hass, firstStat.statistic_id, meta)
unit !== getDisplayUnit(this.hass, statistic_id, meta)
) {
// Clear unit if not all statistics have same unit
unit = null;
@ -363,8 +362,8 @@ class StatisticsChart extends LitElement {
let prevDate: Date | null = null;
// Process chart data.
let firstSum: number | null = null;
let prevSum: number | null = null;
let firstSum: number | null | undefined = null;
let prevSum: number | null | undefined = null;
stats.forEach((stat) => {
const date = new Date(stat.start);
if (prevDate === date) {
@ -373,16 +372,16 @@ class StatisticsChart extends LitElement {
prevDate = date;
const dataValues: Array<number | null> = [];
statTypes.forEach((type) => {
let val: number | null;
let val: number | null | undefined;
if (type === "sum") {
if (firstSum === null) {
if (firstSum === null || firstSum === undefined) {
val = 0;
firstSum = stat.sum;
} else {
val = (stat.sum || 0) - firstSum;
}
} else if (type === "change") {
if (prevSum === null) {
if (prevSum === null || prevSum === undefined) {
prevSum = stat.sum;
return;
}
@ -391,7 +390,11 @@ class StatisticsChart extends LitElement {
} else {
val = stat[type];
}
dataValues.push(val !== null ? Math.round(val * 100) / 100 : null);
dataValues.push(
val !== null && val !== undefined
? Math.round(val * 100) / 100
: null
);
});
pushData(date, dataValues);
});

View File

@ -410,7 +410,8 @@ const getEnergyData = async (
end,
energyStatIds,
period,
energyUnits
energyUnits,
["sum"]
)),
...(await fetchStatistics(
hass!,
@ -418,7 +419,8 @@ const getEnergyData = async (
end,
waterStatIds,
period,
waterUnits
waterUnits,
["sum"]
)),
};
@ -443,7 +445,8 @@ const getEnergyData = async (
endCompare,
energyStatIds,
period,
energyUnits
energyUnits,
["sum"]
)),
...(await fetchStatistics(
hass!,
@ -451,7 +454,8 @@ const getEnergyData = async (
end,
waterStatIds,
period,
waterUnits
waterUnits,
["sum"]
)),
};
}
@ -485,8 +489,8 @@ const getEnergyData = async (
if (stat.length && new Date(stat[0].start) > startMinHour) {
stat.unshift({
...stat[0],
start: startMinHour.toISOString(),
end: startMinHour.toISOString(),
start: startMinHour.getTime(),
end: startMinHour.getTime(),
sum: 0,
state: 0,
});

View File

@ -9,15 +9,14 @@ export interface Statistics {
}
export interface StatisticValue {
statistic_id: string;
start: string;
end: string;
last_reset: string | null;
max: number | null;
mean: number | null;
min: number | null;
sum: number | null;
state: number | null;
start: number;
end: number;
last_reset?: number | null;
max?: number | null;
mean?: number | null;
min?: number | null;
sum?: number | null;
state?: number | null;
}
export interface Statistic {
@ -91,6 +90,16 @@ export interface StatisticsUnitConfiguration {
volume?: "L" | "gal" | "ft³" | "m³";
}
const statisticTypes = [
"last_reset",
"max",
"mean",
"min",
"state",
"sum",
] as const;
export type StatisticsTypes = typeof statisticTypes[number][];
export interface StatisticsValidationResults {
[statisticId: string]: StatisticsValidationResult[];
}
@ -119,7 +128,8 @@ export const fetchStatistics = (
endTime?: Date,
statistic_ids?: string[],
period: "5minute" | "hour" | "day" | "week" | "month" = "hour",
units?: StatisticsUnitConfiguration
units?: StatisticsUnitConfiguration,
types?: StatisticsTypes
) =>
hass.callWS<Statistics>({
type: "recorder/statistics_during_period",
@ -128,6 +138,7 @@ export const fetchStatistics = (
statistic_ids,
period,
units,
types,
});
export const fetchStatistic = (
@ -189,11 +200,11 @@ export const calculateStatisticSumGrowth = (
return null;
}
const endSum = values[values.length - 1].sum;
if (endSum === null) {
if (endSum === null || endSum === undefined) {
return null;
}
const startSum = values[0].sum;
if (startSum === null) {
if (startSum === null || startSum === undefined) {
return endSum;
}
return endSum - startSum;
@ -248,17 +259,19 @@ export const statisticsMetaHasType = (
export const adjustStatisticsSum = (
hass: HomeAssistant,
statistic_id: string,
start_time: string,
start_time: number,
adjustment: number,
adjustment_unit_of_measurement: string | null
): Promise<void> =>
hass.callWS({
): Promise<void> => {
const start_time_iso = new Date(start_time).toISOString();
return hass.callWS({
type: "recorder/adjust_sum_statistics",
statistic_id,
start_time,
start_time_iso,
adjustment,
adjustment_unit_of_measurement,
});
};
export const getStatisticLabel = (
hass: HomeAssistant,

View File

@ -11,6 +11,7 @@ import {
fetchStatistics,
getStatisticMetadata,
Statistics,
StatisticsTypes,
} from "../../data/recorder";
import { HomeAssistant } from "../../types";
import "../../components/chart/statistics-chart";
@ -22,7 +23,7 @@ declare global {
}
}
const statTypes = ["state", "min", "mean", "max"];
const statTypes: StatisticsTypes = ["state", "min", "mean", "max"];
@customElement("ha-more-info-history")
export class MoreInfoHistory extends LitElement {
@ -124,7 +125,9 @@ export class MoreInfoHistory extends LitElement {
subHours(new Date(), 24),
undefined,
[this.entityId],
"5minute"
"5minute",
undefined,
statTypes
);
return;
}

View File

@ -202,8 +202,8 @@ export class HuiEnergyDevicesGraphCard
if (stat.length && new Date(stat[0].start) > startMinHour) {
stat.unshift({
...stat[0],
start: startMinHour.toISOString(),
end: startMinHour.toISOString(),
start: startMinHour.getTime(),
end: startMinHour.getTime(),
sum: 0,
state: 0,
});
@ -228,8 +228,8 @@ export class HuiEnergyDevicesGraphCard
if (stat.length && new Date(stat[0].start) > startMinHour) {
stat.unshift({
...stat[0],
start: startCompareMinHour.toISOString(),
end: startCompareMinHour.toISOString(),
start: startCompareMinHour.getTime(),
end: startCompareMinHour.getTime(),
sum: 0,
state: 0,
});

View File

@ -348,7 +348,7 @@ export class HuiEnergyGasGraphCard
: gasColor;
let prevValue: number | null = null;
let prevStart: string | null = null;
let prevStart: number | null = null;
const gasConsumptionData: ScatterDataPoint[] = [];
@ -357,10 +357,10 @@ export class HuiEnergyGasGraphCard
const stats = statistics[source.stat_energy_from];
for (const point of stats) {
if (point.sum === null) {
if (point.sum === null || point.sum === undefined) {
continue;
}
if (prevValue === null) {
if (prevValue === null || prevValue === undefined) {
prevValue = point.sum;
continue;
}

View File

@ -368,7 +368,7 @@ export class HuiEnergySolarGraphCard
: solarColor;
let prevValue: number | null = null;
let prevStart: string | null = null;
let prevStart: number | null = null;
const solarProductionData: ScatterDataPoint[] = [];
@ -377,10 +377,10 @@ export class HuiEnergySolarGraphCard
const stats = statistics[source.stat_energy_from];
for (const point of stats) {
if (point.sum === null) {
if (point.sum === null || point.sum === undefined) {
continue;
}
if (prevValue === null) {
if (prevValue === null || prevValue === undefined) {
prevValue = point.sum;
continue;
}

View File

@ -484,7 +484,7 @@ export class HuiEnergyUsageGraphCard
const set = {};
let prevValue: number;
stats.forEach((stat) => {
if (stat.sum === null) {
if (stat.sum === null || stat.sum === undefined) {
return;
}
if (prevValue === undefined) {

View File

@ -346,7 +346,7 @@ export class HuiEnergyWaterGraphCard
: waterColor;
let prevValue: number | null = null;
let prevStart: string | null = null;
let prevStart: number | null = null;
const waterConsumptionData: ScatterDataPoint[] = [];
@ -355,10 +355,10 @@ export class HuiEnergyWaterGraphCard
const stats = statistics[source.stat_energy_from];
for (const point of stats) {
if (point.sum === null) {
if (point.sum === null || point.sum === undefined) {
continue;
}
if (prevValue === null) {
if (prevValue === null || prevValue === undefined) {
prevValue = point.sum;
continue;
}

View File

@ -17,6 +17,7 @@ import {
getStatisticMetadata,
Statistics,
StatisticsMetaData,
StatisticsTypes,
} from "../../../data/recorder";
import { HomeAssistant } from "../../../types";
import { findEntities } from "../common/find-entities";
@ -69,6 +70,8 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
private _interval?: number;
private _statTypes?: StatisticsTypes;
public disconnectedCallback() {
super.disconnectedCallback();
if (this._interval) {
@ -117,15 +120,13 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
});
if (typeof config.stat_types === "string") {
this._config = { ...config, stat_types: [config.stat_types] };
this._statTypes = [config.stat_types];
} else if (!config.stat_types) {
this._config = {
...config,
stat_types: ["state", "sum", "min", "max", "mean"],
};
this._statTypes = ["state", "sum", "min", "max", "mean"];
} else {
this._config = config;
this._statTypes = config.stat_types;
}
this._config = config;
}
protected shouldUpdate(changedProps: PropertyValues): boolean {
@ -191,7 +192,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
.statisticsData=${this._statistics}
.metadata=${this._metadata}
.chartType=${this._config.chart_type || "line"}
.statTypes=${this._config.stat_types!}
.statTypes=${this._statTypes!}
.names=${this._names}
.unit=${this._unit}
></statistics-chart>
@ -250,7 +251,8 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
undefined,
this._entities,
this._config!.period,
unitconfig
unitconfig,
this._statTypes
);
} catch (err) {
this._statistics = undefined;