Created
April 28, 2021 22:22
-
-
Save balloob/4a70c83287ddba4e9085cb578ffb161f to your computer and use it in GitHub Desktop.
Lovelace strategy to show all batteries grouped by area.
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
/* | |
Battery strategy that shows your battery entities grouped by area. | |
To use: | |
- store this file in `<config>/www/balloob-battery-strategy.js` | |
- Add lovelace resource: `/local/balloob-battery-strategy.js`, type JavaScript Module | |
- Create a new Lovelace dashboard and set as content: | |
views: | |
- title: Batteries | |
strategy: | |
type: 'custom:balloob-battery' | |
// Optional options. Will be merged into the grid/sensor configs. | |
options: | |
gridOptions: | |
columns: 3 | |
sensorOptions: | |
graph: none | |
*/ | |
const stateObj2Card = (stateObj, strategyOptions, groupName) => { | |
const card = { | |
type: "sensor", | |
entity: stateObj.entity_id, | |
graph: "line", | |
...strategyOptions.sensorOptions, | |
}; | |
// If we have a group name, remove it from the entity name | |
// Example: In group Bedroom, changes Bedroom Lights -> Lights | |
if (groupName) { | |
const entityName = stateObj.attributes.friendly_name; | |
if (entityName && entityName.startsWith(`${groupName} `)) { | |
card.name = entityName.substr(groupName.length + 1); | |
} | |
} | |
return card; | |
}; | |
const createGridCard = (title, cards, strategyOptions) => ({ | |
type: "grid", | |
columns: 2, | |
title, | |
cards, | |
...strategyOptions.gridOptions, | |
}); | |
class BatteryStrategy { | |
/* | |
info: { | |
view: LovelaceViewConfig; | |
config: LovelaceConfig; | |
hass: HomeAssistant; | |
narrow: boolean | undefined; | |
} | |
*/ | |
static async generateView(info) { | |
const strategyOptions = info.view.strategy.options || {}; | |
const [areas, devices, entities] = await Promise.all([ | |
info.hass.callWS({ type: "config/area_registry/list" }), | |
info.hass.callWS({ type: "config/device_registry/list" }), | |
info.hass.callWS({ type: "config/entity_registry/list" }), | |
]); | |
const entityLookup = Object.fromEntries( | |
entities.map((ent) => [ent.entity_id, ent]) | |
); | |
const deviceLookup = Object.fromEntries( | |
devices.map((dev) => [dev.id, dev]) | |
); | |
// Find all battery sensors | |
let states = Object.values(info.hass.states).filter( | |
(stateObj) => | |
stateObj.entity_id.startsWith("sensor.") && | |
stateObj.attributes.device_class == "battery" | |
); | |
const gridCards = []; | |
for (const area of areas) { | |
const processed = new Set(); | |
const areaEntities = []; | |
for (const stateObj of states) { | |
const entry = entityLookup[stateObj.entity_id]; | |
if (!entry) { | |
continue; | |
} | |
if (entry.area_id) { | |
if (entry.area_id !== area.area_id) { | |
continue; | |
} | |
} else if (entry.device_id) { | |
const device = deviceLookup[entry.device_id]; | |
if (!device || device.area_id !== area.area_id) { | |
continue; | |
} | |
} else { | |
continue; | |
} | |
areaEntities.push(stateObj); | |
processed.add(stateObj); | |
} | |
if (areaEntities.length > 0) { | |
gridCards.push( | |
createGridCard( | |
area.name, | |
areaEntities.map((stateObj) => | |
stateObj2Card(stateObj, strategyOptions, area.name) | |
), | |
strategyOptions | |
) | |
); | |
} | |
states = states.filter((stateObj) => !processed.has(stateObj)); | |
if (states.length === 0) break; | |
} | |
// Entities without state | |
if (states.length > 0) { | |
gridCards.push( | |
createGridCard( | |
"No Area", | |
states.map((stateObj) => stateObj2Card(stateObj, strategyOptions)), | |
strategyOptions | |
) | |
); | |
} | |
return { | |
cards: gridCards, | |
}; | |
} | |
} | |
customElements.define("ll-strategy-balloob-battery", BatteryStrategy); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for sharing
I personally did not like so "big" cards for the batteries so I modified the code to generate
entities
card for every area.