Infer a limited history chart from state object (#19176)

* Infer a limited history chart from state object

* bugfix

* bugfix

* minor fixes from feedback
This commit is contained in:
karwosts 2024-02-28 10:20:56 -05:00 committed by GitHub
parent 94f74308d8
commit dd98ec771d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 60 additions and 18 deletions

View File

@ -111,7 +111,7 @@ export class StateHistoryChartLine extends LitElement {
config: this.hass.config, config: this.hass.config,
}, },
}, },
suggestedMin: this.startTime, min: this.startTime,
suggestedMax: this.endTime, suggestedMax: this.endTime,
ticks: { ticks: {
maxRotation: 0, maxRotation: 0,

View File

@ -114,7 +114,7 @@ export class StateHistoryChartTimeline extends LitElement {
config: this.hass.config, config: this.hass.config,
}, },
}, },
suggestedMin: this.startTime, min: this.startTime,
suggestedMax: this.endTime, suggestedMax: this.endTime,
ticks: { ticks: {
autoSkip: true, autoSkip: true,

View File

@ -233,16 +233,32 @@ export class StateHistoryCharts extends LitElement {
new Date().getTime() - 60 * 60 * this.hoursToShow * 1000 new Date().getTime() - 60 * 60 * this.hoursToShow * 1000
); );
} else { } else {
this._computedStartTime = new Date( let minTimeAll = (this.historyData?.timeline ?? []).reduce(
(this.historyData?.timeline ?? []).reduce( (minTime, stateInfo) =>
(minTime, stateInfo) => Math.min(
Math.min( minTime,
minTime, new Date(stateInfo.data[0].last_changed).getTime()
new Date(stateInfo.data[0].last_changed).getTime() ),
), new Date().getTime()
new Date().getTime()
)
); );
minTimeAll = (this.historyData?.line ?? []).reduce(
(minTimeLine, line) =>
Math.min(
minTimeLine,
line.data.reduce(
(minTimeData, data) =>
Math.min(
minTimeData,
new Date(data.states[0].last_changed).getTime()
),
minTimeLine
)
),
minTimeAll
);
this._computedStartTime = new Date(minTimeAll);
} }
} }
} }

View File

@ -205,7 +205,9 @@ export class TimelineController extends BarController {
const y = vScale.getPixelForValue(this.index); const y = vScale.getPixelForValue(this.index);
const xStart = iScale.getPixelForValue(data.start.getTime()); const xStart = iScale.getPixelForValue(
Math.max(iScale.min, data.start.getTime())
);
const xEnd = iScale.getPixelForValue(data.end.getTime()); const xEnd = iScale.getPixelForValue(data.end.getTime());
const width = xEnd - xStart; const width = xEnd - xStart;

View File

@ -49,7 +49,7 @@ export class TimeLineScale extends TimeScale {
max = isFinite(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit); max = isFinite(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit);
// Make sure that max is strictly higher than min (required by the lookup table) // Make sure that max is strictly higher than min (required by the lookup table)
this.min = Math.min(min, max - 1); this.min = adapter.parse(options.min, this) ?? Math.min(min, max - 1);
this.max = Math.max(min + 1, max); this.max = adapter.parse(options.max, this) ?? Math.max(min + 1, max);
} }
} }

View File

@ -81,7 +81,7 @@ export interface EntityHistoryState {
/** attributes */ /** attributes */
a: { [key: string]: any }; a: { [key: string]: any };
/** last_changed; if set, also applies to lu */ /** last_changed; if set, also applies to lu */
lc: number; lc?: number;
/** last_updated */ /** last_updated */
lu: number; lu: number;
} }
@ -419,17 +419,37 @@ const BLANK_UNIT = " ";
export const computeHistory = ( export const computeHistory = (
hass: HomeAssistant, hass: HomeAssistant,
stateHistory: HistoryStates, stateHistory: HistoryStates,
entityIds: string[],
localize: LocalizeFunc, localize: LocalizeFunc,
sensorNumericalDeviceClasses: string[], sensorNumericalDeviceClasses: string[],
splitDeviceClasses = false splitDeviceClasses = false
): HistoryResult => { ): HistoryResult => {
const lineChartDevices: { [unit: string]: HistoryStates } = {}; const lineChartDevices: { [unit: string]: HistoryStates } = {};
const timelineDevices: TimelineEntity[] = []; const timelineDevices: TimelineEntity[] = [];
if (!stateHistory) {
const localStateHistory: HistoryStates = {};
// Create a limited history from stateObj if entity has no recorded history.
const allEntities = new Set([...entityIds, ...Object.keys(stateHistory)]);
allEntities.forEach((entity) => {
if (entity in stateHistory) {
localStateHistory[entity] = stateHistory[entity];
} else if (hass.states[entity]) {
localStateHistory[entity] = [
{
s: hass.states[entity].state,
a: hass.states[entity].attributes,
lu: new Date(hass.states[entity].last_updated).getTime() / 1000,
},
];
}
});
if (!localStateHistory) {
return { line: [], timeline: [] }; return { line: [], timeline: [] };
} }
Object.keys(stateHistory).forEach((entityId) => { Object.keys(localStateHistory).forEach((entityId) => {
const stateInfo = stateHistory[entityId]; const stateInfo = localStateHistory[entityId];
if (stateInfo.length === 0) { if (stateInfo.length === 0) {
return; return;
} }

View File

@ -228,6 +228,7 @@ export class MoreInfoHistory extends LitElement {
this._stateHistory = computeHistory( this._stateHistory = computeHistory(
this.hass!, this.hass!,
combinedHistory, combinedHistory,
[this.entityId],
this.hass!.localize, this.hass!.localize,
sensorNumericDeviceClasses sensorNumericDeviceClasses
); );

View File

@ -433,6 +433,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
this._statisticsHistory = computeHistory( this._statisticsHistory = computeHistory(
this.hass, this.hass,
statsHistoryStates, statsHistoryStates,
[],
this.hass.localize, this.hass.localize,
sensorNumericDeviceClasses, sensorNumericDeviceClasses,
true true
@ -472,6 +473,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
this._stateHistory = computeHistory( this._stateHistory = computeHistory(
this.hass, this.hass,
history, history,
entityIds,
this.hass.localize, this.hass.localize,
sensorNumericDeviceClasses, sensorNumericDeviceClasses,
true true

View File

@ -120,6 +120,7 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
this._stateHistory = computeHistory( this._stateHistory = computeHistory(
this.hass!, this.hass!,
combinedHistory, combinedHistory,
this._entityIds,
this.hass!.localize, this.hass!.localize,
sensorNumericDeviceClasses, sensorNumericDeviceClasses,
this._config?.split_device_classes this._config?.split_device_classes