diff --git a/.devcontainer/ui-lovelace.yaml b/.devcontainer/ui-lovelace.yaml index b59de7d..f9521d9 100644 --- a/.devcontainer/ui-lovelace.yaml +++ b/.devcontainer/ui-lovelace.yaml @@ -1286,3 +1286,15 @@ views: [start.getTime(), 30], [now_minus10.getTime(), 30] ]; + - type: custom:apexcharts-card + graph_span: 2h + header: + show: true + title: second serie should cover first hour + all_series_config: + stroke_width: 1 + series: + - entity: sensor.random0_100 + - entity: sensor.random0_100 + time_delta: -1h + offset: -1h diff --git a/README.md b/README.md index 084ebdd..8498e93 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,7 @@ The card stricly validates all the options available (but not for the `apex_conf | `transform` | string | | v1.5.0 | Transform your raw data in any way you like. See [transform](#transform-option) | | `data_generator` | string | | v1.2.0 | See [data_generator](#data_generator-option) | | `offset` | string | | v1.3.0 | This is different from the main `offset` parameter. This is at the series level. It is only usefull if you want to display data from for eg. yesterday on top of the data from today for the same sensor and compare the data. The time displayed in the tooltip will be wrong as will the x axis information. Valid values are any negative time string, eg: `-1h`, `-12min`, `-1d`, `-1h25`, `-10sec`, ... `month` (365.25 days / 12) and `year` (365.25 days) as unit will generate inconsistent result, you should use days instead. | +| `time_delta` | string | | NEXT_VERSION | This applies a time delta to all the datapoints of your chart **after** fetching them. You can cumulate it with `offset`. Valid values are any time strings starting with `+` or `-`, eg: `-30min`, `+2h`, `-2d`, ... | | `min` | number | `0` | v1.4.0 | Only used when `chart_type = radialBar`, see [chart_type](#chart_type-options). Used to convert the value into a percentage. Minimum value of the sensor | | `max` | number | `100` | v1.4.0 | Only used when `chart_type = radialBar`, see [chart_type](#chart_type-options). Used to convert the value into a percentage. Maximum value of the sensor | | `color_threshold` | object | | v1.6.0 | See [experimental](#experimental-features) | diff --git a/src/apexcharts-card.ts b/src/apexcharts-card.ts index 2e94e7a..1b441e0 100644 --- a/src/apexcharts-card.ts +++ b/src/apexcharts-card.ts @@ -152,6 +152,8 @@ class ChartsCard extends LitElement { private _seriesOffset: number[] = []; + private _seriesTimeDelta: number[] = []; + private _updateDelay: number = DEFAULT_UPDATE_DELAY; private _brushInit = false; @@ -342,6 +344,9 @@ class ChartsCard extends LitElement { if (serie.offset) { this._seriesOffset[index] = validateOffset(serie.offset, `series[${index}].offset`); } + if (serie.time_delta) { + this._seriesTimeDelta[index] = validateOffset(serie.time_delta, `series[${index}].time_delta`); + } }); if (configDup.update_delay) { this._updateDelay = validateInterval(configDup.update_delay, `update_delay`); @@ -769,18 +774,23 @@ class ChartsCard extends LitElement { return; } let data: EntityCachePoints = []; + const offset = (this._seriesOffset[index] || 0) - (this._seriesTimeDelta[index] || 0); + if (offset) { + data = offsetData(graph.history, offset); + } else { + data = [...graph.history]; + } if (this._config?.series[index].type !== 'column' && this._config?.series[index].extend_to) { - if (this._config?.series[index].extend_to === 'end') { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const lastPoint = data.slice(-1)[0]!; + if (this._config?.series[index].extend_to === 'end' && lastPoint[0] < end.getTime()) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - data = [...graph.history, ...([[end.getTime(), graph.history.slice(-1)[0]![1]]] as EntityCachePoints)]; - } else if (this._config?.series[index].extend_to === 'now') { + data.push([end.getTime(), lastPoint[1]]); + } else if (this._config?.series[index].extend_to === 'now' && lastPoint[0] < now.getTime()) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - data = [...graph.history, ...([[now.getTime(), graph.history.slice(-1)[0]![1]]] as EntityCachePoints)]; + data.push([now.getTime(), lastPoint[1]]); } - } else { - data = graph.history; } - data = offsetData(data, this._seriesOffset[index]); const result = this._config?.series[index].invert ? { data: this._invertData(data) } : { data }; if (this._config?.series[index].show.in_chart) graphData.series.push(result); if (this._config?.series[index].show.in_brush) brushData.series.push(result); diff --git a/src/types-config-ti.ts b/src/types-config-ti.ts index b37b2e6..3a8fb6c 100644 --- a/src/types-config-ti.ts +++ b/src/types-config-ti.ts @@ -78,6 +78,7 @@ export const ChartCardAllSeriesExternalConfig = t.iface([], { "min": t.opt("number"), "max": t.opt("number"), "offset": t.opt("string"), + "time_delta": t.opt("string"), "fill_raw": t.opt("GroupByFill"), "show": t.opt("ChartCardSeriesShowConfigExt"), "group_by": t.opt(t.iface([], { diff --git a/src/types-config.ts b/src/types-config.ts index b0212c7..7786bfa 100644 --- a/src/types-config.ts +++ b/src/types-config.ts @@ -78,6 +78,7 @@ export interface ChartCardAllSeriesExternalConfig { min?: number; max?: number; offset?: string; + time_delta?: string; fill_raw?: GroupByFill; show?: ChartCardSeriesShowConfigExt; group_by?: {