Use backend for day month stats in energy dashboard (#10728)
parent
d5fc751da6
commit
fd6785b593
|
@ -82,6 +82,9 @@ export const mockEnergy = (hass: MockHomeAssistant) => {
|
|||
],
|
||||
}));
|
||||
hass.mockWS("energy/info", () => ({ cost_sensors: [] }));
|
||||
hass.mockWS("energy/fossil_energy_consumption", ({ period }) => ({
|
||||
start: period === "month" ? 500 : period === "day" ? 20 : 5,
|
||||
}));
|
||||
const todayString = format(startOfToday(), "yyyy-MM-dd");
|
||||
const tomorrowString = format(startOfTomorrow(), "yyyy-MM-dd");
|
||||
hass.mockWS(
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { addHours, differenceInHours, endOfDay } from "date-fns";
|
||||
import {
|
||||
addDays,
|
||||
addHours,
|
||||
addMonths,
|
||||
differenceInHours,
|
||||
endOfDay,
|
||||
} from "date-fns";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { StatisticValue } from "../../../src/data/history";
|
||||
import { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||
|
@ -70,6 +76,7 @@ const generateMeanStatistics = (
|
|||
id: string,
|
||||
start: Date,
|
||||
end: Date,
|
||||
period: "5minute" | "hour" | "day" | "month" = "hour",
|
||||
initValue: number,
|
||||
maxDiff: number
|
||||
) => {
|
||||
|
@ -84,6 +91,7 @@ const generateMeanStatistics = (
|
|||
statistics.push({
|
||||
statistic_id: id,
|
||||
start: currentDate.toISOString(),
|
||||
end: currentDate.toISOString(),
|
||||
mean,
|
||||
min: mean - Math.random() * maxDiff,
|
||||
max: mean + Math.random() * maxDiff,
|
||||
|
@ -92,7 +100,12 @@ const generateMeanStatistics = (
|
|||
sum: null,
|
||||
});
|
||||
lastVal = mean;
|
||||
currentDate = addHours(currentDate, 1);
|
||||
currentDate =
|
||||
period === "day"
|
||||
? addDays(currentDate, 1)
|
||||
: period === "month"
|
||||
? addMonths(currentDate, 1)
|
||||
: addHours(currentDate, 1);
|
||||
}
|
||||
return statistics;
|
||||
};
|
||||
|
@ -101,6 +114,7 @@ const generateSumStatistics = (
|
|||
id: string,
|
||||
start: Date,
|
||||
end: Date,
|
||||
period: "5minute" | "hour" | "day" | "month" = "hour",
|
||||
initValue: number,
|
||||
maxDiff: number
|
||||
) => {
|
||||
|
@ -115,6 +129,7 @@ const generateSumStatistics = (
|
|||
statistics.push({
|
||||
statistic_id: id,
|
||||
start: currentDate.toISOString(),
|
||||
end: currentDate.toISOString(),
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
|
@ -122,7 +137,12 @@ const generateSumStatistics = (
|
|||
state: initValue + sum,
|
||||
sum,
|
||||
});
|
||||
currentDate = addHours(currentDate, 1);
|
||||
currentDate =
|
||||
period === "day"
|
||||
? addDays(currentDate, 1)
|
||||
: period === "month"
|
||||
? addMonths(currentDate, 1)
|
||||
: addHours(currentDate, 1);
|
||||
}
|
||||
return statistics;
|
||||
};
|
||||
|
@ -131,6 +151,7 @@ const generateCurvedStatistics = (
|
|||
id: string,
|
||||
start: Date,
|
||||
end: Date,
|
||||
_period: "5minute" | "hour" | "day" | "month" = "hour",
|
||||
initValue: number,
|
||||
maxDiff: number,
|
||||
metered: boolean
|
||||
|
@ -149,6 +170,7 @@ const generateCurvedStatistics = (
|
|||
statistics.push({
|
||||
statistic_id: id,
|
||||
start: currentDate.toISOString(),
|
||||
end: currentDate.toISOString(),
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
|
@ -167,11 +189,38 @@ const generateCurvedStatistics = (
|
|||
|
||||
const statisticsFunctions: Record<
|
||||
string,
|
||||
(id: string, start: Date, end: Date) => StatisticValue[]
|
||||
(
|
||||
id: string,
|
||||
start: Date,
|
||||
end: Date,
|
||||
period: "5minute" | "hour" | "day" | "month"
|
||||
) => StatisticValue[]
|
||||
> = {
|
||||
"sensor.energy_consumption_tarif_1": (id: string, start: Date, end: Date) => {
|
||||
"sensor.energy_consumption_tarif_1": (
|
||||
id: string,
|
||||
start: Date,
|
||||
end: Date,
|
||||
period = "hour"
|
||||
) => {
|
||||
if (period !== "hour") {
|
||||
return generateSumStatistics(
|
||||
id,
|
||||
start,
|
||||
end,
|
||||
period,
|
||||
0,
|
||||
period === "day" ? 17 : 504
|
||||
);
|
||||
}
|
||||
const morningEnd = new Date(start.getTime() + 10 * 60 * 60 * 1000);
|
||||
const morningLow = generateSumStatistics(id, start, morningEnd, 0, 0.7);
|
||||
const morningLow = generateSumStatistics(
|
||||
id,
|
||||
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!
|
||||
|
@ -180,6 +229,7 @@ const statisticsFunctions: Record<
|
|||
id,
|
||||
morningEnd,
|
||||
eveningStart,
|
||||
period,
|
||||
morningFinalVal,
|
||||
0
|
||||
);
|
||||
|
@ -187,39 +237,71 @@ const statisticsFunctions: Record<
|
|||
id,
|
||||
eveningStart,
|
||||
end,
|
||||
period,
|
||||
morningFinalVal,
|
||||
0.7
|
||||
);
|
||||
return [...morningLow, ...empty, ...eveningLow];
|
||||
},
|
||||
"sensor.energy_consumption_tarif_2": (id: string, start: Date, end: Date) => {
|
||||
"sensor.energy_consumption_tarif_2": (
|
||||
id: string,
|
||||
start: Date,
|
||||
end: Date,
|
||||
period = "hour"
|
||||
) => {
|
||||
if (period !== "hour") {
|
||||
return generateSumStatistics(
|
||||
id,
|
||||
start,
|
||||
end,
|
||||
period,
|
||||
0,
|
||||
period === "day" ? 17 : 504
|
||||
);
|
||||
}
|
||||
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,
|
||||
0,
|
||||
0.3
|
||||
);
|
||||
const highTarifFinalVal = highTarif.length
|
||||
? highTarif[highTarif.length - 1].sum!
|
||||
: 0;
|
||||
const morning = generateSumStatistics(id, start, morningEnd, 0, 0);
|
||||
const morning = generateSumStatistics(id, start, morningEnd, period, 0, 0);
|
||||
const evening = generateSumStatistics(
|
||||
id,
|
||||
eveningStart,
|
||||
end,
|
||||
period,
|
||||
highTarifFinalVal,
|
||||
0
|
||||
);
|
||||
return [...morning, ...highTarif, ...evening];
|
||||
},
|
||||
"sensor.energy_production_tarif_1": (id, start, end) =>
|
||||
generateSumStatistics(id, start, end, 0, 0),
|
||||
"sensor.energy_production_tarif_1_compensation": (id, start, end) =>
|
||||
generateSumStatistics(id, start, end, 0, 0),
|
||||
"sensor.energy_production_tarif_2": (id, start, end) => {
|
||||
"sensor.energy_production_tarif_1": (id, start, end, period = "hour") =>
|
||||
generateSumStatistics(id, start, end, period, 0, 0),
|
||||
"sensor.energy_production_tarif_1_compensation": (
|
||||
id,
|
||||
start,
|
||||
end,
|
||||
period = "hour"
|
||||
) => generateSumStatistics(id, start, end, period, 0, 0),
|
||||
"sensor.energy_production_tarif_2": (id, start, end, period = "hour") => {
|
||||
if (period !== "hour") {
|
||||
return generateSumStatistics(
|
||||
id,
|
||||
start,
|
||||
end,
|
||||
period,
|
||||
0,
|
||||
period === "day" ? 17 : 504
|
||||
);
|
||||
}
|
||||
const productionStart = new Date(start.getTime() + 9 * 60 * 60 * 1000);
|
||||
const productionEnd = new Date(start.getTime() + 21 * 60 * 60 * 1000);
|
||||
const dayEnd = new Date(endOfDay(productionEnd));
|
||||
|
@ -227,6 +309,7 @@ const statisticsFunctions: Record<
|
|||
id,
|
||||
productionStart,
|
||||
productionEnd,
|
||||
period,
|
||||
0,
|
||||
0.15,
|
||||
true
|
||||
|
@ -234,18 +317,43 @@ const statisticsFunctions: Record<
|
|||
const productionFinalVal = production.length
|
||||
? production[production.length - 1].sum!
|
||||
: 0;
|
||||
const morning = generateSumStatistics(id, start, productionStart, 0, 0);
|
||||
const morning = generateSumStatistics(
|
||||
id,
|
||||
start,
|
||||
productionStart,
|
||||
period,
|
||||
0,
|
||||
0
|
||||
);
|
||||
const evening = generateSumStatistics(
|
||||
id,
|
||||
productionEnd,
|
||||
dayEnd,
|
||||
period,
|
||||
productionFinalVal,
|
||||
0
|
||||
);
|
||||
const rest = generateSumStatistics(id, dayEnd, end, productionFinalVal, 1);
|
||||
const rest = generateSumStatistics(
|
||||
id,
|
||||
dayEnd,
|
||||
end,
|
||||
period,
|
||||
productionFinalVal,
|
||||
1
|
||||
);
|
||||
return [...morning, ...production, ...evening, ...rest];
|
||||
},
|
||||
"sensor.solar_production": (id, start, end) => {
|
||||
"sensor.solar_production": (id, start, end, period = "hour") => {
|
||||
if (period !== "hour") {
|
||||
return generateSumStatistics(
|
||||
id,
|
||||
start,
|
||||
end,
|
||||
period,
|
||||
0,
|
||||
period === "day" ? 17 : 504
|
||||
);
|
||||
}
|
||||
const productionStart = new Date(start.getTime() + 7 * 60 * 60 * 1000);
|
||||
const productionEnd = new Date(start.getTime() + 23 * 60 * 60 * 1000);
|
||||
const dayEnd = new Date(endOfDay(productionEnd));
|
||||
|
@ -253,6 +361,7 @@ const statisticsFunctions: Record<
|
|||
id,
|
||||
productionStart,
|
||||
productionEnd,
|
||||
period,
|
||||
0,
|
||||
0.3,
|
||||
true
|
||||
|
@ -260,19 +369,32 @@ const statisticsFunctions: Record<
|
|||
const productionFinalVal = production.length
|
||||
? production[production.length - 1].sum!
|
||||
: 0;
|
||||
const morning = generateSumStatistics(id, start, productionStart, 0, 0);
|
||||
const morning = generateSumStatistics(
|
||||
id,
|
||||
start,
|
||||
productionStart,
|
||||
period,
|
||||
0,
|
||||
0
|
||||
);
|
||||
const evening = generateSumStatistics(
|
||||
id,
|
||||
productionEnd,
|
||||
dayEnd,
|
||||
period,
|
||||
productionFinalVal,
|
||||
0
|
||||
);
|
||||
const rest = generateSumStatistics(id, dayEnd, end, productionFinalVal, 2);
|
||||
const rest = generateSumStatistics(
|
||||
id,
|
||||
dayEnd,
|
||||
end,
|
||||
period,
|
||||
productionFinalVal,
|
||||
2
|
||||
);
|
||||
return [...morning, ...production, ...evening, ...rest];
|
||||
},
|
||||
"sensor.grid_fossil_fuel_percentage": (id, start, end) =>
|
||||
generateMeanStatistics(id, start, end, 35, 1.3),
|
||||
};
|
||||
|
||||
export const mockHistory = (mockHass: MockHomeAssistant) => {
|
||||
|
@ -347,7 +469,7 @@ export const mockHistory = (mockHass: MockHomeAssistant) => {
|
|||
mockHass.mockWS("history/list_statistic_ids", () => []);
|
||||
mockHass.mockWS(
|
||||
"history/statistics_during_period",
|
||||
({ statistic_ids, start_time, end_time }, hass) => {
|
||||
({ statistic_ids, start_time, end_time, period }, hass) => {
|
||||
const start = new Date(start_time);
|
||||
const end = end_time ? new Date(end_time) : new Date();
|
||||
|
||||
|
@ -355,7 +477,7 @@ export const mockHistory = (mockHass: MockHomeAssistant) => {
|
|||
|
||||
statistic_ids.forEach((id: string) => {
|
||||
if (id in statisticsFunctions) {
|
||||
statistics[id] = statisticsFunctions[id](id, start, end);
|
||||
statistics[id] = statisticsFunctions[id](id, start, end, period);
|
||||
} else {
|
||||
const entityState = hass.states[id];
|
||||
const state = entityState ? Number(entityState.state) : 1;
|
||||
|
@ -365,6 +487,7 @@ export const mockHistory = (mockHass: MockHomeAssistant) => {
|
|||
id,
|
||||
start,
|
||||
end,
|
||||
period,
|
||||
state,
|
||||
state * (state > 80 ? 0.01 : 0.05)
|
||||
)
|
||||
|
@ -372,6 +495,7 @@ export const mockHistory = (mockHass: MockHomeAssistant) => {
|
|||
id,
|
||||
start,
|
||||
end,
|
||||
period,
|
||||
state,
|
||||
state * (state > 80 ? 0.05 : 0.1)
|
||||
);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
addHours,
|
||||
differenceInDays,
|
||||
endOfToday,
|
||||
endOfYesterday,
|
||||
startOfToday,
|
||||
|
@ -191,6 +192,27 @@ export const saveEnergyPreferences = async (
|
|||
return newPrefs;
|
||||
};
|
||||
|
||||
export interface FossilEnergyConsumption {
|
||||
[date: string]: number;
|
||||
}
|
||||
|
||||
export const getFossilEnergyConsumption = async (
|
||||
hass: HomeAssistant,
|
||||
startTime: Date,
|
||||
energy_statistic_ids: string[],
|
||||
co2_statistic_id: string,
|
||||
endTime?: Date,
|
||||
period: "5minute" | "hour" | "day" | "month" = "hour"
|
||||
) =>
|
||||
hass.callWS<FossilEnergyConsumption>({
|
||||
type: "energy/fossil_energy_consumption",
|
||||
start_time: startTime.toISOString(),
|
||||
end_time: endTime?.toISOString(),
|
||||
energy_statistic_ids,
|
||||
co2_statistic_id,
|
||||
period,
|
||||
});
|
||||
|
||||
interface EnergySourceByType {
|
||||
grid?: GridSourceTypeEnergyPreference[];
|
||||
solar?: SolarSourceTypeEnergyPreference[];
|
||||
|
@ -209,6 +231,7 @@ export interface EnergyData {
|
|||
stats: Statistics;
|
||||
co2SignalConfigEntry?: ConfigEntry;
|
||||
co2SignalEntity?: string;
|
||||
fossilEnergyConsumption?: FossilEnergyConsumption;
|
||||
}
|
||||
|
||||
const getEnergyData = async (
|
||||
|
@ -246,12 +269,9 @@ const getEnergyData = async (
|
|||
}
|
||||
}
|
||||
|
||||
const consumptionStatIDs: string[] = [];
|
||||
const statIDs: string[] = [];
|
||||
|
||||
if (co2SignalEntity !== undefined) {
|
||||
statIDs.push(co2SignalEntity);
|
||||
}
|
||||
|
||||
for (const source of prefs.energy_sources) {
|
||||
if (source.type === "solar") {
|
||||
statIDs.push(source.stat_energy_from);
|
||||
|
@ -278,6 +298,7 @@ const getEnergyData = async (
|
|||
|
||||
// grid source
|
||||
for (const flowFrom of source.flow_from) {
|
||||
consumptionStatIDs.push(flowFrom.stat_energy_from);
|
||||
statIDs.push(flowFrom.stat_energy_from);
|
||||
if (flowFrom.stat_cost) {
|
||||
statIDs.push(flowFrom.stat_cost);
|
||||
|
@ -299,7 +320,44 @@ const getEnergyData = async (
|
|||
}
|
||||
}
|
||||
|
||||
const stats = await fetchStatistics(hass!, addHours(start, -1), end, statIDs); // Subtract 1 hour from start to get starting point data
|
||||
const dayDifference = differenceInDays(end || new Date(), start);
|
||||
|
||||
// Subtract 1 hour from start to get starting point data
|
||||
const startMinHour = addHours(start, -1);
|
||||
|
||||
const stats = await fetchStatistics(
|
||||
hass!,
|
||||
startMinHour,
|
||||
end,
|
||||
statIDs,
|
||||
dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour"
|
||||
);
|
||||
|
||||
let fossilEnergyConsumption: FossilEnergyConsumption | undefined;
|
||||
|
||||
if (co2SignalEntity !== undefined) {
|
||||
fossilEnergyConsumption = await getFossilEnergyConsumption(
|
||||
hass!,
|
||||
start,
|
||||
consumptionStatIDs,
|
||||
co2SignalEntity,
|
||||
end,
|
||||
dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour"
|
||||
);
|
||||
}
|
||||
|
||||
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.toISOString(),
|
||||
end: startMinHour.toISOString(),
|
||||
sum: 0,
|
||||
state: 0,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const data = {
|
||||
start,
|
||||
|
@ -309,6 +367,7 @@ const getEnergyData = async (
|
|||
stats,
|
||||
co2SignalConfigEntry,
|
||||
co2SignalEntity,
|
||||
fossilEnergyConsumption,
|
||||
};
|
||||
|
||||
return data;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { addDays, addMonths, startOfDay, startOfMonth } from "date-fns";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { computeStateDisplay } from "../common/entity/compute_state_display";
|
||||
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
||||
|
@ -63,6 +62,7 @@ export interface Statistics {
|
|||
export interface StatisticValue {
|
||||
statistic_id: string;
|
||||
start: string;
|
||||
end: string;
|
||||
last_reset: string | null;
|
||||
max: number | null;
|
||||
mean: number | null;
|
||||
|
@ -350,7 +350,7 @@ export const fetchStatistics = (
|
|||
startTime: Date,
|
||||
endTime?: Date,
|
||||
statistic_ids?: string[],
|
||||
period: "hour" | "5minute" = "hour"
|
||||
period: "5minute" | "hour" | "day" | "month" = "hour"
|
||||
) =>
|
||||
hass.callWS<Statistics>({
|
||||
type: "history/statistics_during_period",
|
||||
|
@ -428,151 +428,3 @@ export const statisticsHaveType = (
|
|||
stats: StatisticValue[],
|
||||
type: StatisticType
|
||||
) => stats.some((stat) => stat[type] !== null);
|
||||
|
||||
// Merge the growth of multiple sum statistics into one
|
||||
const mergeSumGrowthStatistics = (stats: StatisticValue[][]) => {
|
||||
const result = {};
|
||||
|
||||
stats.forEach((stat) => {
|
||||
if (stat.length === 0) {
|
||||
return;
|
||||
}
|
||||
let prevSum: number | null = null;
|
||||
stat.forEach((statVal) => {
|
||||
if (statVal.sum === null) {
|
||||
return;
|
||||
}
|
||||
if (prevSum === null) {
|
||||
prevSum = statVal.sum;
|
||||
return;
|
||||
}
|
||||
const growth = statVal.sum - prevSum;
|
||||
if (statVal.start in result) {
|
||||
result[statVal.start] += growth;
|
||||
} else {
|
||||
result[statVal.start] = growth;
|
||||
}
|
||||
prevSum = statVal.sum;
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the growth of a statistic over the given period while applying a
|
||||
* per-period percentage.
|
||||
*/
|
||||
export const calculateStatisticsSumGrowthWithPercentage = (
|
||||
percentageStat: StatisticValue[],
|
||||
sumStats: StatisticValue[][]
|
||||
): number | null => {
|
||||
let sum: number | null = null;
|
||||
|
||||
if (sumStats.length === 0 || percentageStat.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sumGrowthToProcess = mergeSumGrowthStatistics(sumStats);
|
||||
|
||||
percentageStat.forEach((percentageStatValue) => {
|
||||
const sumGrowth = sumGrowthToProcess[percentageStatValue.start];
|
||||
if (sumGrowth === undefined) {
|
||||
return;
|
||||
}
|
||||
if (sum === null) {
|
||||
sum = sumGrowth * (percentageStatValue.mean! / 100);
|
||||
} else {
|
||||
sum += sumGrowth * (percentageStatValue.mean! / 100);
|
||||
}
|
||||
});
|
||||
|
||||
return sum;
|
||||
};
|
||||
|
||||
export const reduceSumStatisticsByDay = (
|
||||
values: StatisticValue[]
|
||||
): StatisticValue[] => {
|
||||
if (!values?.length) {
|
||||
return [];
|
||||
}
|
||||
const result: StatisticValue[] = [];
|
||||
if (
|
||||
values.length > 1 &&
|
||||
new Date(values[0].start).getDate() === new Date(values[1].start).getDate()
|
||||
) {
|
||||
// add init value if the first value isn't end of previous period
|
||||
result.push({
|
||||
...values[0]!,
|
||||
start: startOfDay(addDays(new Date(values[0].start), -1)).toISOString(),
|
||||
});
|
||||
}
|
||||
let lastValue: StatisticValue;
|
||||
let prevDate: number | undefined;
|
||||
for (const value of values) {
|
||||
const date = new Date(value.start).getDate();
|
||||
if (prevDate === undefined) {
|
||||
prevDate = date;
|
||||
}
|
||||
if (prevDate !== date) {
|
||||
// Last value of the day
|
||||
result.push({
|
||||
...lastValue!,
|
||||
start: startOfDay(new Date(lastValue!.start)).toISOString(),
|
||||
});
|
||||
prevDate = date;
|
||||
}
|
||||
lastValue = value;
|
||||
}
|
||||
// Add final value
|
||||
result.push({
|
||||
...lastValue!,
|
||||
start: startOfDay(new Date(lastValue!.start)).toISOString(),
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
export const reduceSumStatisticsByMonth = (
|
||||
values: StatisticValue[]
|
||||
): StatisticValue[] => {
|
||||
if (!values?.length) {
|
||||
return [];
|
||||
}
|
||||
const result: StatisticValue[] = [];
|
||||
if (
|
||||
values.length > 1 &&
|
||||
new Date(values[0].start).getMonth() ===
|
||||
new Date(values[1].start).getMonth()
|
||||
) {
|
||||
// add init value if the first value isn't end of previous period
|
||||
result.push({
|
||||
...values[0]!,
|
||||
start: startOfMonth(
|
||||
addMonths(new Date(values[0].start), -1)
|
||||
).toISOString(),
|
||||
});
|
||||
}
|
||||
let lastValue: StatisticValue;
|
||||
let prevMonth: number | undefined;
|
||||
for (const value of values) {
|
||||
const month = new Date(value.start).getMonth();
|
||||
if (prevMonth === undefined) {
|
||||
prevMonth = month;
|
||||
}
|
||||
if (prevMonth !== month) {
|
||||
// Last value of the month
|
||||
result.push({
|
||||
...lastValue!,
|
||||
start: startOfMonth(new Date(lastValue!.start)).toISOString(),
|
||||
});
|
||||
prevMonth = month;
|
||||
}
|
||||
lastValue = value;
|
||||
}
|
||||
// Add final value
|
||||
result.push({
|
||||
...lastValue!,
|
||||
start: startOfMonth(new Date(lastValue!.start)).toISOString(),
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
|
|
@ -13,10 +13,7 @@ import {
|
|||
energySourcesByType,
|
||||
getEnergyDataCollection,
|
||||
} from "../../../../data/energy";
|
||||
import {
|
||||
calculateStatisticsSumGrowth,
|
||||
calculateStatisticsSumGrowthWithPercentage,
|
||||
} from "../../../../data/history";
|
||||
import { calculateStatisticsSumGrowth } from "../../../../data/history";
|
||||
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import { createEntityNotFoundWarning } from "../../components/hui-warning";
|
||||
|
@ -90,19 +87,13 @@ class HuiEnergyCarbonGaugeCard
|
|||
value = 100;
|
||||
}
|
||||
|
||||
if (
|
||||
this._data.co2SignalEntity in this._data.stats &&
|
||||
totalGridConsumption
|
||||
) {
|
||||
const highCarbonEnergy =
|
||||
calculateStatisticsSumGrowthWithPercentage(
|
||||
this._data.stats[this._data.co2SignalEntity],
|
||||
types
|
||||
.grid![0].flow_from.map(
|
||||
(flow) => this._data!.stats![flow.stat_energy_from]
|
||||
)
|
||||
.filter(Boolean)
|
||||
) || 0;
|
||||
if (this._data.fossilEnergyConsumption && totalGridConsumption) {
|
||||
const highCarbonEnergy = this._data.fossilEnergyConsumption
|
||||
? Object.values(this._data.fossilEnergyConsumption).reduce(
|
||||
(sum, a) => sum + a,
|
||||
0
|
||||
)
|
||||
: 0;
|
||||
|
||||
const totalSolarProduction = types.solar
|
||||
? calculateStatisticsSumGrowth(
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
ScatterDataPoint,
|
||||
} from "chart.js";
|
||||
import { getRelativePosition } from "chart.js/helpers";
|
||||
import { addHours } from "date-fns";
|
||||
import { addHours, differenceInDays } from "date-fns";
|
||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
|
@ -155,13 +155,19 @@ export class HuiEnergyDevicesGraphCard
|
|||
);
|
||||
|
||||
private async _getStatistics(energyData: EnergyData): Promise<void> {
|
||||
const dayDifference = differenceInDays(
|
||||
energyData.end || new Date(),
|
||||
energyData.start
|
||||
);
|
||||
|
||||
this._data = await fetchStatistics(
|
||||
this.hass,
|
||||
addHours(energyData.start, -1),
|
||||
energyData.end,
|
||||
energyData.prefs.device_consumption.map(
|
||||
(device) => device.stat_consumption
|
||||
)
|
||||
),
|
||||
dayDifference > 35 ? "month" : dayDifference > 2 ? "day" : "hour"
|
||||
);
|
||||
|
||||
const data: Array<ChartDataset<"bar", ParsedDataType<"bar">>["data"]> = [];
|
||||
|
|
|
@ -24,10 +24,7 @@ import {
|
|||
getEnergyDataCollection,
|
||||
getEnergyGasUnit,
|
||||
} from "../../../../data/energy";
|
||||
import {
|
||||
calculateStatisticsSumGrowth,
|
||||
calculateStatisticsSumGrowthWithPercentage,
|
||||
} from "../../../../data/history";
|
||||
import { calculateStatisticsSumGrowth } from "../../../../data/history";
|
||||
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { LovelaceCard } from "../../types";
|
||||
|
@ -209,19 +206,11 @@ class HuiEnergyDistrubutionCard
|
|||
// This fallback is used in the demo
|
||||
let electricityMapUrl = "https://www.electricitymap.org";
|
||||
|
||||
if (
|
||||
this._data.co2SignalEntity &&
|
||||
this._data.co2SignalEntity in this._data.stats
|
||||
) {
|
||||
if (this._data.co2SignalEntity && this._data.fossilEnergyConsumption) {
|
||||
// Calculate high carbon consumption
|
||||
const highCarbonEnergy = calculateStatisticsSumGrowthWithPercentage(
|
||||
this._data.stats[this._data.co2SignalEntity],
|
||||
types
|
||||
.grid![0].flow_from.map(
|
||||
(flow) => this._data!.stats[flow.stat_energy_from]
|
||||
)
|
||||
.filter(Boolean)
|
||||
);
|
||||
const highCarbonEnergy = Object.values(
|
||||
this._data.fossilEnergyConsumption
|
||||
).reduce((sum, a) => sum + a, 0);
|
||||
|
||||
const co2State = this.hass.states[this._data.co2SignalEntity];
|
||||
|
||||
|
|
|
@ -41,10 +41,6 @@ import {
|
|||
} from "../../../../common/number/format_number";
|
||||
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
|
||||
import { FrontendLocaleData } from "../../../../data/translation";
|
||||
import {
|
||||
reduceSumStatisticsByMonth,
|
||||
reduceSumStatisticsByDay,
|
||||
} from "../../../../data/history";
|
||||
import { formatTime } from "../../../../common/datetime/format_time";
|
||||
|
||||
@customElement("hui-energy-gas-graph-card")
|
||||
|
@ -247,11 +243,6 @@ export class HuiEnergyGasGraphCard
|
|||
.getPropertyValue("--energy-gas-color")
|
||||
.trim();
|
||||
|
||||
const dayDifference = differenceInDays(
|
||||
energyData.end || new Date(),
|
||||
energyData.start
|
||||
);
|
||||
|
||||
gasSources.forEach((source, idx) => {
|
||||
const data: ChartDataset<"bar" | "line">[] = [];
|
||||
const entity = this.hass.states[source.stat_energy_from];
|
||||
|
@ -268,16 +259,7 @@ export class HuiEnergyGasGraphCard
|
|||
|
||||
// Process gas consumption data.
|
||||
if (source.stat_energy_from in energyData.stats) {
|
||||
const stats =
|
||||
dayDifference > 35
|
||||
? reduceSumStatisticsByMonth(
|
||||
energyData.stats[source.stat_energy_from]
|
||||
)
|
||||
: dayDifference > 2
|
||||
? reduceSumStatisticsByDay(
|
||||
energyData.stats[source.stat_energy_from]
|
||||
)
|
||||
: energyData.stats[source.stat_energy_from];
|
||||
const stats = energyData.stats[source.stat_energy_from];
|
||||
|
||||
for (const point of stats) {
|
||||
if (point.sum === null) {
|
||||
|
|
|
@ -42,10 +42,6 @@ import {
|
|||
} from "../../../../common/number/format_number";
|
||||
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
|
||||
import { FrontendLocaleData } from "../../../../data/translation";
|
||||
import {
|
||||
reduceSumStatisticsByMonth,
|
||||
reduceSumStatisticsByDay,
|
||||
} from "../../../../data/history";
|
||||
import { formatTime } from "../../../../common/datetime/format_time";
|
||||
|
||||
@customElement("hui-energy-solar-graph-card")
|
||||
|
@ -274,16 +270,7 @@ export class HuiEnergySolarGraphCard
|
|||
|
||||
// Process solar production data.
|
||||
if (source.stat_energy_from in energyData.stats) {
|
||||
const stats =
|
||||
dayDifference > 35
|
||||
? reduceSumStatisticsByMonth(
|
||||
energyData.stats[source.stat_energy_from]
|
||||
)
|
||||
: dayDifference > 2
|
||||
? reduceSumStatisticsByDay(
|
||||
energyData.stats[source.stat_energy_from]
|
||||
)
|
||||
: energyData.stats[source.stat_energy_from];
|
||||
const stats = energyData.stats[source.stat_energy_from];
|
||||
|
||||
for (const point of stats) {
|
||||
if (point.sum === null) {
|
||||
|
|
|
@ -27,10 +27,6 @@ import {
|
|||
import "../../../../components/chart/ha-chart-base";
|
||||
import "../../../../components/ha-card";
|
||||
import { EnergyData, getEnergyDataCollection } from "../../../../data/energy";
|
||||
import {
|
||||
reduceSumStatisticsByDay,
|
||||
reduceSumStatisticsByMonth,
|
||||
} from "../../../../data/history";
|
||||
import { FrontendLocaleData } from "../../../../data/translation";
|
||||
import { SubscribeMixin } from "../../../../mixins/subscribe-mixin";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
|
@ -298,11 +294,6 @@ export class HuiEnergyUsageGraphCard
|
|||
}
|
||||
}
|
||||
|
||||
const dayDifference = differenceInDays(
|
||||
energyData.end || new Date(),
|
||||
energyData.start
|
||||
);
|
||||
|
||||
this._start = energyData.start;
|
||||
this._end = energyData.end || endOfToday();
|
||||
|
||||
|
@ -368,12 +359,7 @@ export class HuiEnergyUsageGraphCard
|
|||
const totalStats: { [start: string]: number } = {};
|
||||
const sets: { [statId: string]: { [start: string]: number } } = {};
|
||||
statIds!.forEach((id) => {
|
||||
const stats =
|
||||
dayDifference > 35
|
||||
? reduceSumStatisticsByMonth(energyData.stats[id])
|
||||
: dayDifference > 2
|
||||
? reduceSumStatisticsByDay(energyData.stats[id])
|
||||
: energyData.stats[id];
|
||||
const stats = energyData.stats[id];
|
||||
if (!stats) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,576 +0,0 @@
|
|||
import { assert } from "chai";
|
||||
|
||||
import { calculateStatisticsSumGrowthWithPercentage } from "../../src/data/history";
|
||||
|
||||
describe("calculateStatisticsSumGrowthWithPercentage", () => {
|
||||
it("Returns null if not enough values", async () => {
|
||||
assert.strictEqual(
|
||||
calculateStatisticsSumGrowthWithPercentage([], []),
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
it("Returns null if not enough sum stat values", async () => {
|
||||
assert.strictEqual(
|
||||
calculateStatisticsSumGrowthWithPercentage(
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.carbon_intensity",
|
||||
start: "2021-07-28T05:00:00Z",
|
||||
last_reset: null,
|
||||
max: 75,
|
||||
mean: 50,
|
||||
min: 25,
|
||||
sum: null,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.carbon_intensity",
|
||||
start: "2021-07-28T07:00:00Z",
|
||||
last_reset: null,
|
||||
max: 100,
|
||||
mean: 75,
|
||||
min: 50,
|
||||
sum: null,
|
||||
state: null,
|
||||
},
|
||||
],
|
||||
[]
|
||||
),
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
it("Returns null if not enough percentage stat values", async () => {
|
||||
assert.strictEqual(
|
||||
calculateStatisticsSumGrowthWithPercentage(
|
||||
[],
|
||||
[
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T04:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 50,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T05:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 100,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T07:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 200,
|
||||
state: null,
|
||||
},
|
||||
],
|
||||
]
|
||||
),
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
it("Returns a percentage of the growth", async () => {
|
||||
assert.strictEqual(
|
||||
calculateStatisticsSumGrowthWithPercentage(
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.carbon_intensity",
|
||||
start: "2021-07-28T05:00:00Z",
|
||||
last_reset: null,
|
||||
max: 75,
|
||||
mean: 50,
|
||||
min: 25,
|
||||
sum: null,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.carbon_intensity",
|
||||
start: "2021-07-28T07:00:00Z",
|
||||
last_reset: null,
|
||||
max: 100,
|
||||
mean: 75,
|
||||
min: 50,
|
||||
sum: null,
|
||||
state: null,
|
||||
},
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T04:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 50,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T05:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 100,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T07:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 200,
|
||||
state: null,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.off_peak_consumption",
|
||||
start: "2021-07-28T04:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 50,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.off_peak_consumption",
|
||||
start: "2021-07-28T05:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 100,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.off_peak_consumption",
|
||||
start: "2021-07-28T07:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 200,
|
||||
state: null,
|
||||
},
|
||||
],
|
||||
]
|
||||
),
|
||||
200
|
||||
);
|
||||
});
|
||||
|
||||
it("It ignores sum data that doesnt match start", async () => {
|
||||
assert.strictEqual(
|
||||
calculateStatisticsSumGrowthWithPercentage(
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.carbon_intensity",
|
||||
start: "2021-07-28T05:00:00Z",
|
||||
last_reset: null,
|
||||
max: 75,
|
||||
mean: 50,
|
||||
min: 25,
|
||||
sum: null,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.carbon_intensity",
|
||||
start: "2021-07-28T07:00:00Z",
|
||||
last_reset: null,
|
||||
max: 100,
|
||||
mean: 75,
|
||||
min: 50,
|
||||
sum: null,
|
||||
state: null,
|
||||
},
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T04:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 50,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T04:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 50,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T05:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 100,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T07:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 200,
|
||||
state: null,
|
||||
},
|
||||
],
|
||||
]
|
||||
),
|
||||
100
|
||||
);
|
||||
});
|
||||
|
||||
it("It ignores percentage data that doesnt match start", async () => {
|
||||
assert.strictEqual(
|
||||
calculateStatisticsSumGrowthWithPercentage(
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.carbon_intensity",
|
||||
start: "2021-07-28T04:00:00Z",
|
||||
last_reset: null,
|
||||
max: 25,
|
||||
mean: 25,
|
||||
min: 25,
|
||||
sum: null,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.carbon_intensity",
|
||||
start: "2021-07-28T05:00:00Z",
|
||||
last_reset: null,
|
||||
max: 75,
|
||||
mean: 50,
|
||||
min: 25,
|
||||
sum: null,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.carbon_intensity",
|
||||
start: "2021-07-28T07:00:00Z",
|
||||
last_reset: null,
|
||||
max: 100,
|
||||
mean: 75,
|
||||
min: 50,
|
||||
sum: null,
|
||||
state: null,
|
||||
},
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T04:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 50,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T05:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 100,
|
||||
state: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.peak_consumption",
|
||||
start: "2021-07-28T07:00:00Z",
|
||||
last_reset: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
min: null,
|
||||
sum: 200,
|
||||
state: null,
|
||||
},
|
||||
],
|
||||
]
|
||||
),
|
||||
100
|
||||
);
|
||||
});
|
||||
|
||||
it("Returns a percentage of the growth", async () => {
|
||||
assert.strictEqual(
|
||||
calculateStatisticsSumGrowthWithPercentage(
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T06:00:00.000Z",
|
||||
mean: 10,
|
||||
min: 10,
|
||||
max: 10,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 10,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T07:00:00.000Z",
|
||||
mean: 20,
|
||||
min: 20,
|
||||
max: 20,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 20,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T08:00:00.000Z",
|
||||
mean: 30,
|
||||
min: 30,
|
||||
max: 30,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 30,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T09:00:00.000Z",
|
||||
mean: 40,
|
||||
min: 40,
|
||||
max: 40,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 40,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T10:00:00.000Z",
|
||||
mean: 50,
|
||||
min: 50,
|
||||
max: 50,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 50,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T11:00:00.000Z",
|
||||
mean: 60,
|
||||
min: 60,
|
||||
max: 60,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 60,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T12:00:00.000Z",
|
||||
mean: 70,
|
||||
min: 70,
|
||||
max: 70,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 70,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T13:00:00.000Z",
|
||||
mean: 80,
|
||||
min: 80,
|
||||
max: 80,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 80,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T14:00:00.000Z",
|
||||
mean: 90,
|
||||
min: 90,
|
||||
max: 90,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 90,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T15:00:00.000Z",
|
||||
mean: 100,
|
||||
min: 100,
|
||||
max: 100,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 100,
|
||||
sum: null,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.grid_fossil_fuel_percentage",
|
||||
start: "2021-08-03T16:00:00.000Z",
|
||||
mean: 110,
|
||||
min: 110,
|
||||
max: 110,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 120,
|
||||
sum: null,
|
||||
},
|
||||
],
|
||||
[
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T06:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 10,
|
||||
sum: 10,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T07:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 20,
|
||||
sum: 20,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T08:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 30,
|
||||
sum: 30,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T09:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 40,
|
||||
sum: 40,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T10:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 50,
|
||||
sum: 50,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T11:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 60,
|
||||
sum: 60,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T12:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 70,
|
||||
sum: 70,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T13:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 80,
|
||||
sum: 80,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T14:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 90,
|
||||
sum: 90,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_1",
|
||||
start: "2021-08-03T15:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 100,
|
||||
sum: 100,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_2",
|
||||
start: "2021-08-03T15:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 10,
|
||||
sum: 10,
|
||||
},
|
||||
{
|
||||
statistic_id: "sensor.energy_consumption_tarif_2",
|
||||
start: "2021-08-03T16:00:00.000Z",
|
||||
mean: null,
|
||||
min: null,
|
||||
max: null,
|
||||
last_reset: "1970-01-01T00:00:00+00:00",
|
||||
state: 20,
|
||||
sum: 20,
|
||||
},
|
||||
],
|
||||
]
|
||||
),
|
||||
65
|
||||
);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue