Load registries in core, wait them to be loaded before generating das… (#19356)

* load registries in core, wait them to be loaded before generating dashboard

* import

* improve

* Split out subscribe functions
This commit is contained in:
Bram Kragten 2024-01-11 09:48:20 +01:00 committed by GitHub
parent b9069b25ad
commit 03751d2581
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 153 additions and 115 deletions

View File

@ -1,11 +1,10 @@
import { Connection, createCollection } from "home-assistant-js-websocket";
import { Store } from "home-assistant-js-websocket/dist/store";
import { stringCompare } from "../common/string/compare";
import { debounce } from "../common/util/debounce";
import { HomeAssistant } from "../types";
import { DeviceRegistryEntry } from "./device_registry";
import { EntityRegistryEntry } from "./entity_registry";
export { subscribeAreaRegistry } from "./ws-area_registry";
export interface AreaRegistryEntry {
area_id: string;
name: string;
@ -53,45 +52,6 @@ export const deleteAreaRegistryEntry = (hass: HomeAssistant, areaId: string) =>
area_id: areaId,
});
const fetchAreaRegistry = (conn: Connection) =>
conn
.sendMessagePromise({
type: "config/area_registry/list",
})
.then((areas) =>
(areas as AreaRegistryEntry[]).sort((ent1, ent2) =>
stringCompare(ent1.name, ent2.name)
)
);
const subscribeAreaRegistryUpdates = (
conn: Connection,
store: Store<AreaRegistryEntry[]>
) =>
conn.subscribeEvents(
debounce(
() =>
fetchAreaRegistry(conn).then((areas: AreaRegistryEntry[]) =>
store.setState(areas, true)
),
500,
true
),
"area_registry_updated"
);
export const subscribeAreaRegistry = (
conn: Connection,
onChange: (areas: AreaRegistryEntry[]) => void
) =>
createCollection<AreaRegistryEntry[]>(
"_areaRegistry",
fetchAreaRegistry,
subscribeAreaRegistryUpdates,
conn,
onChange
);
export const getAreaEntityLookup = (
entities: EntityRegistryEntry[]
): AreaEntityLookup => {

View File

@ -1,8 +1,5 @@
import { Connection, createCollection } from "home-assistant-js-websocket";
import type { Store } from "home-assistant-js-websocket/dist/store";
import { computeStateName } from "../common/entity/compute_state_name";
import { caseInsensitiveStringCompare } from "../common/string/compare";
import { debounce } from "../common/util/debounce";
import type { HomeAssistant } from "../types";
import type {
EntityRegistryDisplayEntry,
@ -10,6 +7,11 @@ import type {
} from "./entity_registry";
import type { EntitySources } from "./entity_sources";
export {
fetchDeviceRegistry,
subscribeDeviceRegistry,
} from "./ws-device_registry";
export interface DeviceRegistryEntry {
id: string;
config_entries: string[];
@ -96,39 +98,6 @@ export const removeConfigEntryFromDevice = (
config_entry_id: configEntryId,
});
export const fetchDeviceRegistry = (conn: Connection) =>
conn.sendMessagePromise<DeviceRegistryEntry[]>({
type: "config/device_registry/list",
});
const subscribeDeviceRegistryUpdates = (
conn: Connection,
store: Store<DeviceRegistryEntry[]>
) =>
conn.subscribeEvents(
debounce(
() =>
fetchDeviceRegistry(conn).then((devices) =>
store.setState(devices, true)
),
500,
true
),
"device_registry_updated"
);
export const subscribeDeviceRegistry = (
conn: Connection,
onChange: (devices: DeviceRegistryEntry[]) => void
) =>
createCollection<DeviceRegistryEntry[]>(
"_dr",
fetchDeviceRegistry,
subscribeDeviceRegistryUpdates,
conn,
onChange
);
export const sortDeviceRegistryByName = (
entries: DeviceRegistryEntry[],
language: string

View File

@ -8,6 +8,8 @@ import { HomeAssistant } from "../types";
import { LightColor } from "./light";
import { computeDomain } from "../common/entity/compute_domain";
export { subscribeEntityRegistryDisplay } from "./ws-entity_registry_display";
type entityCategory = "config" | "diagnostic";
export interface EntityRegistryDisplayEntry {
@ -22,7 +24,7 @@ export interface EntityRegistryDisplayEntry {
display_precision?: number;
}
interface EntityRegistryDisplayEntryResponse {
export interface EntityRegistryDisplayEntryResponse {
entities: {
ei: string;
di?: string;
@ -255,34 +257,6 @@ export const subscribeEntityRegistry = (
onChange
);
const subscribeEntityRegistryDisplayUpdates = (
conn: Connection,
store: Store<EntityRegistryDisplayEntryResponse>
) =>
conn.subscribeEvents(
debounce(
() =>
fetchEntityRegistryDisplay(conn).then((entities) =>
store.setState(entities, true)
),
500,
true
),
"entity_registry_updated"
);
export const subscribeEntityRegistryDisplay = (
conn: Connection,
onChange: (entities: EntityRegistryDisplayEntryResponse) => void
) =>
createCollection<EntityRegistryDisplayEntryResponse>(
"_entityRegistryDisplay",
fetchEntityRegistryDisplay,
subscribeEntityRegistryDisplayUpdates,
conn,
onChange
);
export const sortEntityRegistryByName = (
entries: EntityRegistryEntry[],
language: string

View File

@ -0,0 +1,44 @@
import { Connection, createCollection } from "home-assistant-js-websocket";
import { Store } from "home-assistant-js-websocket/dist/store";
import { stringCompare } from "../common/string/compare";
import { AreaRegistryEntry } from "./area_registry";
import { debounce } from "../common/util/debounce";
const fetchAreaRegistry = (conn: Connection) =>
conn
.sendMessagePromise({
type: "config/area_registry/list",
})
.then((areas) =>
(areas as AreaRegistryEntry[]).sort((ent1, ent2) =>
stringCompare(ent1.name, ent2.name)
)
);
const subscribeAreaRegistryUpdates = (
conn: Connection,
store: Store<AreaRegistryEntry[]>
) =>
conn.subscribeEvents(
debounce(
() =>
fetchAreaRegistry(conn).then((areas: AreaRegistryEntry[]) =>
store.setState(areas, true)
),
500,
true
),
"area_registry_updated"
);
export const subscribeAreaRegistry = (
conn: Connection,
onChange: (areas: AreaRegistryEntry[]) => void
) =>
createCollection<AreaRegistryEntry[]>(
"_areaRegistry",
fetchAreaRegistry,
subscribeAreaRegistryUpdates,
conn,
onChange
);

View File

@ -0,0 +1,37 @@
import { Connection, createCollection } from "home-assistant-js-websocket";
import { Store } from "home-assistant-js-websocket/dist/store";
import { DeviceRegistryEntry } from "./device_registry";
import { debounce } from "../common/util/debounce";
export const fetchDeviceRegistry = (conn: Connection) =>
conn.sendMessagePromise<DeviceRegistryEntry[]>({
type: "config/device_registry/list",
});
const subscribeDeviceRegistryUpdates = (
conn: Connection,
store: Store<DeviceRegistryEntry[]>
) =>
conn.subscribeEvents(
debounce(
() =>
fetchDeviceRegistry(conn).then((devices) =>
store.setState(devices, true)
),
500,
true
),
"device_registry_updated"
);
export const subscribeDeviceRegistry = (
conn: Connection,
onChange: (devices: DeviceRegistryEntry[]) => void
) =>
createCollection<DeviceRegistryEntry[]>(
"_dr",
fetchDeviceRegistry,
subscribeDeviceRegistryUpdates,
conn,
onChange
);

View File

@ -0,0 +1,35 @@
import { Connection, createCollection } from "home-assistant-js-websocket";
import { Store } from "home-assistant-js-websocket/dist/store";
import {
EntityRegistryDisplayEntryResponse,
fetchEntityRegistryDisplay,
} from "./entity_registry";
import { debounce } from "../common/util/debounce";
const subscribeEntityRegistryDisplayUpdates = (
conn: Connection,
store: Store<EntityRegistryDisplayEntryResponse>
) =>
conn.subscribeEvents(
debounce(
() =>
fetchEntityRegistryDisplay(conn).then((entities) =>
store.setState(entities, true)
),
500,
true
),
"entity_registry_updated"
);
export const subscribeEntityRegistryDisplay = (
conn: Connection,
onChange: (entities: EntityRegistryDisplayEntryResponse) => void
) =>
createCollection<EntityRegistryDisplayEntryResponse>(
"_entityRegistryDisplay",
fetchEntityRegistryDisplay,
subscribeEntityRegistryDisplayUpdates,
conn,
onChange
);

View File

@ -11,19 +11,22 @@ import {
import { loadTokens, saveTokens } from "../common/auth/token_storage";
import { hassUrl } from "../data/auth";
import { isExternal } from "../data/external";
import { getRecorderInfo } from "../data/recorder";
import { subscribeFrontendUserData } from "../data/frontend";
import { fetchConfig } from "../data/lovelace/config/types";
import { fetchResources } from "../data/lovelace/resource";
import { MAIN_WINDOW_NAME } from "../data/main_window";
import { WindowWithPreloads } from "../data/preloads";
import { getRecorderInfo } from "../data/recorder";
import { subscribeRepairsIssueRegistry } from "../data/repairs";
import { subscribeAreaRegistry } from "../data/ws-area_registry";
import { subscribeDeviceRegistry } from "../data/ws-device_registry";
import { subscribeEntityRegistryDisplay } from "../data/ws-entity_registry_display";
import { subscribePanels } from "../data/ws-panels";
import { subscribeThemes } from "../data/ws-themes";
import { subscribeRepairsIssueRegistry } from "../data/repairs";
import { subscribeUser } from "../data/ws-user";
import type { ExternalAuth } from "../external_app/external_auth";
import "../resources/array.flat.polyfill";
import "../resources/safari-14-attachshadow-patch";
import { MAIN_WINDOW_NAME } from "../data/main_window";
import { WindowWithPreloads } from "../data/preloads";
window.name = MAIN_WINDOW_NAME;
(window as any).frontendVersion = __VERSION__;
@ -113,6 +116,9 @@ window.hassConnection.then(({ conn }) => {
// do nothing
};
subscribeEntities(conn, noop);
subscribeEntityRegistryDisplay(conn, noop);
subscribeDeviceRegistry(conn, noop);
subscribeAreaRegistry(conn, noop);
subscribeConfig(conn, noop);
subscribeServices(conn, noop);
subscribePanels(conn, noop);

View File

@ -1,7 +1,7 @@
import "@material/mwc-button";
import deepFreeze from "deep-freeze";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { html, LitElement, TemplateResult } from "lit";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { constructUrlCurrentPath } from "../../common/url/construct-url";
import {
@ -161,10 +161,15 @@ export class LovelacePanel extends LitElement {
`;
}
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
protected willUpdate(changedProps: PropertyValues) {
super.willUpdate(changedProps);
if (!this.lovelace && this._panelState !== "error") {
this._fetchConfig(false);
}
}
this._fetchConfig(false);
protected firstUpdated(changedProps: PropertyValues): void {
super.firstUpdated(changedProps);
if (!this._unsubUpdates) {
this._subscribeUpdates();
}
@ -267,6 +272,10 @@ export class LovelacePanel extends LitElement {
// If strategy defined, apply it here.
if (isStrategyDashboard(rawConf)) {
if (!this.hass?.entities || !this.hass.devices || !this.hass.areas) {
// We need these to generate a dashboard, wait for them
return;
}
conf = await generateLovelaceDashboardStrategy(
rawConf.strategy,
this.hass!
@ -282,6 +291,10 @@ export class LovelacePanel extends LitElement {
this._errorMsg = err.message;
return;
}
if (!this.hass?.entities || !this.hass.devices || !this.hass.areas) {
// We need these to generate a dashboard, wait for them
return;
}
conf = await generateLovelaceDashboardStrategy(
DEFAULT_CONFIG.strategy,
this.hass!