Skip to content

Commit

Permalink
feat(series): Retrieve an attribute of your entity instead of the sta…
Browse files Browse the repository at this point in the history
…te (#32)

* Support for attributes

* Doc

Fixes #29
  • Loading branch information
RomRider committed Feb 1, 2021
1 parent ef71fa2 commit b76bf16
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 6 deletions.
13 changes: 13 additions & 0 deletions .devcontainer/ui-lovelace.yaml
Expand Up @@ -344,3 +344,16 @@ views:
group_by:
func: sum
duration: 20min

- type: custom:apexcharts-card
graph_span: 1h
update_delay: 5.5s
# apex_config:
# dataLabels:
# enabled: true
header:
show: true
title: Light Brightness (attribute test)
series:
- entity: light.kitchen_lights
attribute: brightness
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -107,6 +107,7 @@ The card stricly validates all the options available (but not for the `apex_conf
| :white_check_mark: `series` | array | | v1.0.0 | See [series](#series-options) |
| `chart_type` | string | `line` | NEXT_VERSION | See [chart_type](#chart_type-options) |
| `update_interval` | string | | v1.1.0 | By default the card updates on every state change. Setting this overrides the behaviour. Valid values are any time string, eg: `1h`, `12min`, `1d`, `1h25`, `10sec`, ... |
| `update_delay` | string | `1500ms` | NEXT_VERSION | If doesn't display the last state but the one before, you'll want to increase this value, don't go over `10s`, it's not necessary. You'll also want to increase this value if you are using `attribute` in the `series`. Valid values are any time strings. This is because of how Home-Assistant works with history, see [here](https://www.home-assistant.io/integrations/recorder/#commit_interval) |
| `graph_span` | string | `24h` | v1.1.0 | The span of the graph as a time interval. Valid values are any time string, eg: `1h`, `12min`, `1d`, `1h25`, `10sec`, ... |
| `span` | object | | v1.2.0 | See [span](#span-options) |
| `show` | object | | v1.0.0 | See [show](#main-show-options) |
Expand All @@ -124,6 +125,7 @@ The card stricly validates all the options available (but not for the `apex_conf
| Name | Type | Default | Since | Description |
| ---- | :--: | :-----: | :---: | ----------- |
| :white_check_mark: `entity` | string | | v1.0.0 | The `entity_id` of the sensor to display |
| `attribute` | string | | NEXT_VERSION | Instead of retrieving the state, it will retrieve an `attribute` of the entity. Make sure you increase `update_delay` if the chart doesn't reflect the last value of the attribute |
| `name` | string | | v1.0.0 | Override the name of the entity |
| `color` | string | | v1.1.0 | Color of the serie. Supported formats: `yellow`, `#aabbcc`, `rgb(128, 128, 128)` or `var(--css-color-variable)` |
| `type` | string | `line` | v1.0.0 | `line`, `area` or `column` are supported for now |
Expand Down
16 changes: 14 additions & 2 deletions src/apexcharts-card.ts
Expand Up @@ -25,7 +25,14 @@ import GraphEntry from './graphEntry';
import { createCheckers } from 'ts-interface-checker';
import { ChartCardExternalConfig, ChartCardSeriesExternalConfig } from './types-config';
import exportedTypeSuite from './types-config-ti';
import { DEFAULT_FLOAT_PRECISION, DEFAULT_SHOW_LEGEND_VALUE, moment, NO_VALUE, TIMESERIES_TYPES } from './const';
import {
DEFAULT_FLOAT_PRECISION,
DEFAULT_SHOW_LEGEND_VALUE,
DEFAULT_UPDATE_DELAY,
moment,
NO_VALUE,
TIMESERIES_TYPES,
} from './const';
import {
DEFAULT_COLORS,
DEFAULT_DURATION,
Expand Down Expand Up @@ -100,6 +107,8 @@ class ChartsCard extends LitElement {

private _seriesOffset: number[] = [];

private _updateDelay: number = DEFAULT_UPDATE_DELAY;

@property({ type: Boolean }) private _warning = false;

public connectedCallback() {
Expand Down Expand Up @@ -186,7 +195,7 @@ class ChartsCard extends LitElement {
// give time to HA's recorder component to write the data in the history
setTimeout(() => {
this._updateData();
}, 1500);
}, this._updateDelay);
}
}
}
Expand All @@ -212,6 +221,9 @@ class ChartsCard extends LitElement {
this._seriesOffset[index] = validateOffset(serie.offset, `series[${index}].offset`);
}
});
if (config.update_delay) {
this._updateDelay = validateInterval(config.update_delay, `update_delay`);
}

this._config = mergeDeep(
{
Expand Down
2 changes: 2 additions & 0 deletions src/const.ts
Expand Up @@ -37,3 +37,5 @@ export const TIMESERIES_TYPES = ['line', 'scatter', undefined];

export const DEFAULT_MIN = 0;
export const DEFAULT_MAX = 100;

export const DEFAULT_UPDATE_DELAY = 1500;
31 changes: 27 additions & 4 deletions src/graphEntry.ts
Expand Up @@ -171,12 +171,33 @@ export default class GraphEntry {
new Date(history.data.slice(-1)[0]![0] + 1)
: startHistory,
end,
skipInitialState,
this._config.attribute ? false : skipInitialState,
this._config.attribute ? true : false,
);
if (newHistory && newHistory[0] && newHistory[0].length > 0) {
/*
hack because HA doesn't return anything if skipInitialState is false
when retrieving for attributes so we retrieve it and we remove it.
*/
if (this._config.attribute && skipInitialState) {
newHistory[0].shift();
}
const newStateHistory: EntityCachePoints = newHistory[0].map((item) => {
const stateParsed = parseFloat(item.state);
return [new Date(item.last_changed).getTime(), !Number.isNaN(stateParsed) ? stateParsed : null];
let stateParsed: number | null = null;
if (this._config.attribute) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
if (item.attributes && item.attributes![this._config.attribute]) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
stateParsed = parseFloat(item.attributes![this._config.attribute]);
}
} else {
stateParsed = parseFloat(item.state);
}
if (this._config.attribute) {
return [new Date(item.last_updated).getTime(), !Number.isNaN(stateParsed) ? stateParsed : null];
} else {
return [new Date(item.last_changed).getTime(), !Number.isNaN(stateParsed) ? stateParsed : null];
}
});
if (history?.data.length) {
history.span = this._graphSpan;
Expand Down Expand Up @@ -221,13 +242,15 @@ export default class GraphEntry {
start: Date | undefined,
end: Date | undefined,
skipInitialState: boolean,
withAttributes = false,
): Promise<HassHistory | undefined> {
let url = 'history/period';
if (start) url += `/${start.toISOString()}`;
url += `?filter_entity_id=${this._entityID}`;
if (end) url += `&end_time=${end.toISOString()}`;
if (skipInitialState) url += '&skip_initial_state';
url += '&minimal_response';
if (!withAttributes) url += '&minimal_response';
if (withAttributes) url += '&significant_changes_only=0';
return this._hass?.callApi('GET', url);
}

Expand Down
2 changes: 2 additions & 0 deletions src/types-config-ti.ts
Expand Up @@ -8,6 +8,7 @@ export const ChartCardExternalConfig = t.iface([], {
"type": t.lit('custom:apexcharts-card'),
"chart_type": t.opt(t.union(t.lit('line'), t.lit('scatter'), t.lit('pie'), t.lit('donut'), t.lit('radialBar'))),
"update_interval": t.opt("string"),
"update_delay": t.opt("string"),
"series": t.array("ChartCardSeriesExternalConfig"),
"graph_span": t.opt("string"),
"span": t.opt("ChartCardSpanExtConfig"),
Expand All @@ -31,6 +32,7 @@ export const ChartCardSpanExtConfig = t.iface([], {

export const ChartCardSeriesExternalConfig = t.iface([], {
"entity": "string",
"attribute": t.opt("string"),
"name": t.opt("string"),
"type": t.opt(t.union(t.lit('line'), t.lit('column'), t.lit('area'))),
"color": t.opt("string"),
Expand Down
2 changes: 2 additions & 0 deletions src/types-config.ts
Expand Up @@ -2,6 +2,7 @@ export interface ChartCardExternalConfig {
type: 'custom:apexcharts-card';
chart_type?: 'line' | 'scatter' | 'pie' | 'donut' | 'radialBar';
update_interval?: string;
update_delay?: string;
series: ChartCardSeriesExternalConfig[];
graph_span?: string;
span?: ChartCardSpanExtConfig;
Expand All @@ -27,6 +28,7 @@ export interface ChartCardSpanExtConfig {
}
export interface ChartCardSeriesExternalConfig {
entity: string;
attribute?: string;
name?: string;
type?: 'line' | 'column' | 'area';
color?: string;
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Expand Up @@ -43,6 +43,7 @@ export interface HassHistoryEntry {
last_updated: string;
state: string;
last_changed: string;
attributes?: never;
}

export interface HistoryBucket {
Expand Down

0 comments on commit b76bf16

Please sign in to comment.