122 lines
4.6 KiB
JavaScript

import { areaByName, areaDevices, deviceByName, deviceEntities } from "card-tools/src/devices";
function match(pattern, value) {
if(typeof(value) === "string" && typeof(pattern) === "string") {
if((pattern.startsWith('/') && pattern.endsWith('/')) || pattern.indexOf('*') !== -1) {
if(!pattern.startsWith('/')) { // Convert globs to regex
pattern = pattern
.replace(/\./g, '\.')
.replace(/\*/g, '.*');
pattern = `/^${pattern}$/`;
}
let regex = new RegExp(pattern.slice(1,-1));
return regex.test(value);
}
}
if(typeof(pattern) === "string") {
// Comparisons assume numerical values
if(pattern.startsWith("<=")) return parseFloat(value) <= parseFloat(pattern.substr(2));
if(pattern.startsWith(">=")) return parseFloat(value) >= parseFloat(pattern.substr(2));
if(pattern.startsWith("<")) return parseFloat(value) < parseFloat(pattern.substr(1));
if(pattern.startsWith(">")) return parseFloat(value) > parseFloat(pattern.substr(1));
if(pattern.startsWith("!")) return parseFloat(value) != parseFloat(pattern.substr(1));
if(pattern.startsWith("=")) return parseFloat(value) == parseFloat(pattern.substr(1));
}
return pattern === value;
}
export function entity_filter(hass, filter) {
return function(e) {
const entity = typeof(e) === "string"
? hass.states[e]
: hass.states[e.entity];
if(!e) return false;
for (const [key, value] of Object.entries(filter)) {
switch(key.split(" ")[0]) {
case "options":
case "sort":
break;
case "domain":
if(!match(value, entity.entity_id.split('.')[0]))
return false;
break;
case "entity_id":
if(!match(value, entity.entity_id))
return false;
break;
case "state":
if(!match(value, entity.state))
return false;
break;
case "name":
if(!entity.attributes.friendly_name
|| !match(value, entity.attributes.friendly_name))
return false;
break;
case "group":
if(!value.startsWith("group.")
|| !hass.states[value]
|| !hass.states[value].attributes.entity_id
|| !hass.states[value].attributes.entity_id.includes(entity.entity_id)
)
return false;
break;
case "attributes":
for(const [k, v] of Object.entries(value)) {
let attr = k.split(" ")[0];
let entityAttribute = entity.attributes;
while(attr && entityAttribute) {
let step;
[step, attr] = attr.split(":");
entityAttribute = entityAttribute[step];
}
if(entityAttribute === undefined
|| (v && !match(v, entityAttribute))
)
return false;
continue;
}
break;
case "not":
if(entity_filter(hass,value)(e))
return false;
break;
case "device":
let _deviceMatch = false;
for(const d of window.cardToolsData.devices) {
if (match(value, d.name)){
if(deviceEntities(d).includes(entity.entity_id))
_deviceMatch = true;
}
}
if(!_deviceMatch) return false;
break;
case "area":
let _areaMatch = false;
for (const a of window.cardToolsData.areas) {
if(match(value, a.name)) {
if(areaDevices(a).flatMap(deviceEntities).includes(entity.entity_id))
_areaMatch = true;
}
}
if(!_areaMatch) return false;
break;
default:
return false;
}
}
return true;
}
}