Skip to content

Commit

Permalink
feat(#192): use floors in autoconfig and add some sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
MindFreeze committed May 15, 2024
1 parent 4016407 commit 4db709a
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 6 deletions.
10 changes: 7 additions & 3 deletions src/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export class Chart extends LitElement {
connection.calculating = true;
[parent, child].forEach(ent => {
if (ent.type === 'remaining_child_state') {
this.connectionsByParent.get(ent)!.forEach(c => {
this.connectionsByParent.get(ent)?.forEach(c => {
if (!c.ready) {
this.connectionsByChild.get(c.child)?.forEach(conn => {
if (conn !== connection && !conn.calculating) {
Expand All @@ -168,7 +168,7 @@ export class Chart extends LitElement {
}
});
} else if (ent.type === 'remaining_parent_state') {
this.connectionsByChild.get(ent)!.forEach(c => {
this.connectionsByChild.get(ent)?.forEach(c => {
if (!c.ready) {
this.connectionsByParent.get(c.parent)?.forEach(conn => {
if (conn !== connection && !conn.calculating) {
Expand Down Expand Up @@ -543,7 +543,11 @@ export class Chart extends LitElement {
if (entityConf.type === 'remaining_child_state') {
const connections = this.connectionsByParent.get(entityConf);
if (!connections) {
throw new Error('Invalid entity config ' + JSON.stringify(entityConf));
if (entityConf.children.length) {
throw new Error('Invalid entity config ' + JSON.stringify(entityConf));
}
// no children means no state. simplifies autoconfig
return { state: 0, attributes: {} };
}
const state = connections.reduce((sum, c) => (c.ready ? sum + c.state : Infinity), 0);
const childEntity = this._getEntityState(this._findRelatedRealEntity(entityConf, 'children'));
Expand Down
39 changes: 38 additions & 1 deletion src/ha-sankey-chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
getStatistics,
} from './energy';
import { until } from 'lit/directives/until';
import { getEntitiesByArea, HomeAssistantReal } from './hass';
import { fetchFloorRegistry, getEntitiesByArea, HomeAssistantReal } from './hass';
import { LovelaceCardEditor } from 'custom-card-helpers';
import './editor/index';

Expand Down Expand Up @@ -259,6 +259,8 @@ class SankeyChart extends SubscribeMixin(LitElement) {
children: [],
},
],
sort_by: 'state',
sort_group_by_parent: true,
},
{
entities: orderedDeviceIds.map(id => ({
Expand All @@ -267,6 +269,8 @@ class SankeyChart extends SubscribeMixin(LitElement) {
name: names[id],
children: [],
})),
sort_by: 'state',
sort_group_by_parent: true,
},
].filter(s => s.entities.length > 0) as Section[];

Expand Down Expand Up @@ -302,6 +306,39 @@ class SankeyChart extends SubscribeMixin(LitElement) {
});
}

const floors = await fetchFloorRegistry(this.hass);
if (floors.length) {
const orphanAreas = areas.filter(a => !a.area.floor_id);
sections[1].entities[sections[1].entities.length - 1].children = [
...floors.map(f => f.floor_id),
...orphanAreas.map(a => a.area.area_id),
'unknown',
];
sections.splice(2, 0, {
entities: [
...floors.map(
(f): EntityConfigInternal => ({
entity_id: f.floor_id,
type: 'remaining_child_state',
name: f.name,
children: areas.filter(a => a.area.floor_id === f.floor_id).map(a => a.area.area_id),
}),
),
...orphanAreas.map((a): EntityConfigInternal => ({
entity_id: a.area.area_id,
type: 'passthrough',
children: [],
})),
{
entity_id: 'unknown',
type: 'passthrough',
children: [],
},
],
sort_by: 'state',
});
}

this.setNormalizedConfig({ ...this.config, sections });
}

Expand Down
18 changes: 16 additions & 2 deletions src/hass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { HomeAssistant } from 'custom-card-helpers';
export interface Area {
area_id: string;
name: string;
floor_id?: string | null;
}

export interface HomeAssistantReal extends HomeAssistant {
Expand Down Expand Up @@ -53,6 +54,14 @@ export interface ExtEntityRegistryEntry extends EntityRegistryEntry {
original_device_class?: string;
}

export interface FloorRegistryEntry {
aliases: string[];
floor_id: string;
icon?: string;
level?: number;
name: string;
}

export const getExtendedEntityRegistryEntry = (
hass: HomeAssistant,
entityId: string,
Expand All @@ -70,7 +79,12 @@ export const fetchDeviceRegistry = async (hass: HomeAssistant): Promise<DeviceRe
return (devicesCache = await hass.callWS({
type: 'config/device_registry/list',
}));
}
};

export const fetchFloorRegistry = (hass: HomeAssistant): Promise<FloorRegistryEntry[]> =>
hass.callWS({
type: 'config/floor_registry/list',
});

export async function getEntityArea(hass: HomeAssistant, entityId: string) {
try {
Expand All @@ -93,7 +107,7 @@ export async function getEntitiesByArea(hass: HomeAssistantReal, entityIds: stri
const result: Record<string, { area: Area; entities: string[] }> = {};
for (const entityId of entityIds) {
const areaId = await getEntityArea(hass, entityId);
const area = areaId ? hass.areas[areaId] : {area_id: 'no_area', name: 'No area'};
const area = areaId ? hass.areas[areaId] : { area_id: 'no_area', name: 'No area' };
if (!result[area.area_id]) {
result[area.area_id] = { area, entities: [] };
}
Expand Down

0 comments on commit 4db709a

Please sign in to comment.