diff --git a/gallery/src/pages/lovelace/entity-filter-card.ts b/gallery/src/pages/lovelace/entity-filter-card.ts index 879cf3bb71cb..17ada5a29d62 100644 --- a/gallery/src/pages/lovelace/entity-filter-card.ts +++ b/gallery/src/pages/lovelace/entity-filter-card.ts @@ -38,11 +38,36 @@ const ENTITIES = [ getEntity("light", "ceiling_lights", "off", { friendly_name: "Ceiling Lights", }), + getEntity("sensor", "gas_station_auchan_saint_priest_e10", 1.712, { + device_class: "monetary", + icon: "mdi:gas-station", + friendly_name: "Gas station Auchan Saint Priest E10", + unit_of_measurement: "€", + }), + getEntity("sensor", "gas_station_carrefour_venissieux_e10", 1.724, { + device_class: "monetary", + icon: "mdi:gas-station", + friendly_name: "Gas station Carrefour Venissieux E10", + unit_of_measurement: "€", + }), + getEntity("sensor", "gas_station_relais_lyon_mermoz_e10", 1.751, { + device_class: "monetary", + icon: "mdi:gas-station", + friendly_name: "Gas station Relais Lyon Mermoz E10", + unit_of_measurement: "€", + }), + getEntity("sensor", "gas_station_lowest_price", 1.712, { + state_class: "measurement", + min_entity_id: "sensor.gas_station_auchan_saint_priest_e10", + icon: "mdi:gas-station-in-use", + friendly_name: "Gas station Lowest Price", + unit_of_measurement: "€", + }), ]; const CONFIGS = [ { - heading: "Unfiltered controller", + heading: "Unfiltered entities", config: ` - type: entities entities: @@ -52,7 +77,7 @@ const CONFIGS = [ `, }, { - heading: "Filtered entities card", + heading: "Filtered entities", config: ` - type: entity-filter entities: @@ -107,6 +132,43 @@ const CONFIGS = [ title: Custom Title `, }, + { + heading: "Unfiltered number entities", + config: ` +- type: entities + entities: + - sensor.gas_station_auchan_saint_priest_e10 + - sensor.gas_station_carrefour_venissieux_e10 + - sensor.gas_station_relais_lyon_mermoz_e10 + - sensor.gas_station_lowest_price + `, + }, + { + heading: "Filtered entities with operator & number value", + config: ` +- type: entity-filter + entities: + - sensor.gas_station_auchan_saint_priest_e10 + - sensor.gas_station_carrefour_venissieux_e10 + - sensor.gas_station_relais_lyon_mermoz_e10 + state_filter: + - operator: <= + value: 1.73 + `, + }, + { + heading: "Filtered entities with operator & entity_id value", + config: ` +- type: entity-filter + entities: + - sensor.gas_station_auchan_saint_priest_e10 + - sensor.gas_station_carrefour_venissieux_e10 + - sensor.gas_station_relais_lyon_mermoz_e10 + state_filter: + - operator: == + value: sensor.gas_station_lowest_price + `, + }, ]; @customElement("demo-lovelace-entity-filter-card") diff --git a/src/panels/lovelace/badges/hui-entity-filter-badge.ts b/src/panels/lovelace/badges/hui-entity-filter-badge.ts index a45799695ac8..8b724aa91454 100644 --- a/src/panels/lovelace/badges/hui-entity-filter-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-filter-badge.ts @@ -76,23 +76,11 @@ class EntityFilterBadge extends ReactiveElement implements LovelaceBadge { } const entitiesList = this._configEntities.filter((entityConf) => { - const stateObj = this.hass.states[entityConf.entity]; - - if (!stateObj) { - return false; - } - - if (entityConf.state_filter) { - for (const filter of entityConf.state_filter) { - if (evaluateFilter(stateObj, filter)) { - return true; - } - } - } else { - for (const filter of this._config!.state_filter) { - if (evaluateFilter(stateObj, filter)) { - return true; - } + const state_filters = + entityConf.state_filter ?? this._config!.state_filter; + for (const filter of state_filters) { + if (evaluateFilter(this.hass, entityConf.entity, filter)) { + return true; } } diff --git a/src/panels/lovelace/cards/hui-entity-filter-card.ts b/src/panels/lovelace/cards/hui-entity-filter-card.ts index ebd649bc530f..1b9549125bed 100644 --- a/src/panels/lovelace/cards/hui-entity-filter-card.ts +++ b/src/panels/lovelace/cards/hui-entity-filter-card.ts @@ -122,23 +122,11 @@ class EntityFilterCard extends ReactiveElement implements LovelaceCard { } const entitiesList = this._configEntities.filter((entityConf) => { - const stateObj = this.hass!.states[entityConf.entity]; - - if (!stateObj) { - return false; - } - - if (entityConf.state_filter) { - for (const filter of entityConf.state_filter) { - if (evaluateFilter(stateObj, filter)) { - return true; - } - } - } else { - for (const filter of this._config!.state_filter) { - if (evaluateFilter(stateObj, filter)) { - return true; - } + const state_filters = + entityConf.state_filter ?? this._config!.state_filter; + for (const filter of state_filters) { + if (evaluateFilter(this.hass!, entityConf.entity, filter)) { + return true; } } diff --git a/src/panels/lovelace/common/evaluate-filter.ts b/src/panels/lovelace/common/evaluate-filter.ts index 9bc190e494ca..e63e96a4a9bf 100644 --- a/src/panels/lovelace/common/evaluate-filter.ts +++ b/src/panels/lovelace/common/evaluate-filter.ts @@ -1,12 +1,31 @@ import { HassEntity } from "home-assistant-js-websocket"; +import { HomeAssistant } from "../../../types"; + +export const evaluateFilter = ( + hass: HomeAssistant, + current_entity_id: string, + filter: any +): boolean => { + const stateObj: HassEntity = hass.states[current_entity_id]; + + if (!stateObj) { + return false; + } -export const evaluateFilter = (stateObj: HassEntity, filter: any): boolean => { const operator = filter.operator || "=="; let value = filter.value ?? filter; let state = filter.attribute ? stateObj.attributes[filter.attribute] : stateObj.state; + if (typeof value === "string" && value.includes(".")) { + value = hass.states[value]?.state; + + if (!value) { + return false; + } + } + if (operator === "==" || operator === "!=") { const valueIsNumeric = typeof value === "number" ||