Created
March 12, 2019 19:20
-
-
Save randellhodges/7654a267a282b6c4a48b590748d13b9f to your computer and use it in GitHub Desktop.
Lovelace Monster-Card with When Entity Filter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MyMonsterCard extends HTMLElement { | |
_getEntities(hass, filters) { | |
function _filterEntityId(stateObj, pattern) { | |
if (pattern.indexOf('*') === -1) { | |
return stateObj.entity_id === pattern; | |
} | |
const regEx = new RegExp(`^${pattern.replace(/\*/g, '.*')}$`, 'i'); | |
return stateObj.entity_id.search(regEx) === 0; | |
} | |
function _filterName(stateObj, pattern) { | |
let compareEntity = stateObj.attributes.title ? stateObj.attributes.title : stateObj.attributes.friendly_name; | |
if (!compareEntity) compareEntity = stateObj.entity_id; | |
if (pattern.indexOf('*') === -1) { | |
return compareEntity === pattern; | |
} | |
const regEx = new RegExp(`^${pattern.replace(/\*/g, '.*')}$`, 'i'); | |
return compareEntity.search(regEx) === 0; | |
} | |
// Allows '< 300' in b | |
function _complexCompare(a, b) { | |
const _compare = { | |
'>': (x, y) => x > y, | |
'<': (x, y) => x < y, | |
'<=': (x, y) => x <= y, | |
'>=': (x, y) => x >= y, | |
'=': (x, y) => x === y, | |
}; | |
let operator = '='; | |
let y = b; | |
let x = a; | |
if (!isNaN(a) && typeof (b) == 'string' | |
&& b.split(" ").length > 1) { | |
[operator, y] = b.split(' ', 2); | |
x = parseFloat(a); | |
} | |
return _compare[operator](x, y); | |
} | |
const entities = new Map(); | |
filters.forEach((filter) => { | |
const filters = []; | |
if (filter.domain) { | |
filters.push(stateObj => stateObj.entity_id.split('.', 1)[0] === filter.domain); | |
} | |
if (filter.attributes) { | |
Object.keys(filter.attributes).forEach(key => { | |
filters.push(stateObj => _complexCompare(stateObj.attributes[key], filter.attributes[key])); | |
}); | |
} | |
if (filter.entity_id) { | |
filters.push(stateObj => _filterEntityId(stateObj, filter.entity_id)); | |
} | |
if (filter.name) { | |
filters.push(stateObj => _filterName(stateObj, filter.name)); | |
} | |
if (filter.state) { | |
filters.push(stateObj => _complexCompare(stateObj.state, filter.state)); | |
} | |
if (filter.when) { | |
filter.when.forEach(when => { | |
if (when.entity_id) { | |
const whenEntity = hass.states[when.entity_id]; | |
if (whenEntity) { | |
if (when.attributes) { | |
Object.keys(filter.attributes).forEach(key => { | |
filters.push(() => _complexCompare(when.attributes[key], whenEntity.attributes[key])); | |
}); | |
} | |
if (when.state) { | |
filters.push(() => _complexCompare(when.state, whenEntity.state)); | |
} | |
} | |
} | |
}); | |
} | |
const options = filter.options ? filter.options : {} | |
Object.keys(hass.states).sort().forEach(key => { | |
if (filters.every(filterFunc => filterFunc(hass.states[key]))) { | |
entities.set(hass.states[key].entity_id, Object.assign({ "entity": hass.states[key].entity_id }, options)); | |
} | |
}); | |
}); | |
return Array.from(entities.values()); | |
} | |
setConfig(config) { | |
if (!config.filter.include || !Array.isArray(config.filter.include)) { | |
throw new Error('Please define filters'); | |
} | |
if (this.lastChild) this.removeChild(this.lastChild); | |
const cardConfig = Object.assign({}, config); | |
if (!cardConfig.card) cardConfig.card = {}; | |
if (config.card.entities) delete config.card.entities; | |
if (!cardConfig.card.type) cardConfig.card.type = 'entities'; | |
const element = document.createElement(`hui-${cardConfig.card.type}-card`); | |
this.appendChild(element); | |
this._config = cardConfig; | |
} | |
set hass(hass) { | |
const config = this._config; | |
let entities = this._getEntities(hass, config.filter.include); | |
if (config.filter.exclude) { | |
const excludeEntities = this._getEntities(hass, config.filter.exclude).map(entity => entity.entity); | |
entities = entities.filter(entity => !excludeEntities.includes(entity.entity)); | |
} | |
if (entities.length === 0 && config.show_empty === false) { | |
this.style.display = 'none'; | |
} else { | |
if (config.when && (hass.states[config.when.entity].state == config.when.state) || !config.when) { | |
this.style.display = 'block'; | |
} else { | |
this.style.display = 'none'; | |
} | |
} | |
if (!config.card.entities || config.card.entities.length !== entities.length || | |
!config.card.entities.every((value, index) => value.entity === entities[index].entity)) { | |
config.card.entities = entities; | |
this.lastChild.setConfig(config.card); | |
} | |
this.lastChild.hass = hass; | |
} | |
getCardSize() { | |
return 'getCardSize' in this.lastChild ? this.lastChild.getCardSize() : 1; | |
} | |
} | |
customElements.define('my-monster-card', MyMonsterCard); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment