From 03751d2581740e91278fc16ff879adf3d97f8a68 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 11 Jan 2024 09:48:20 +0100 Subject: [PATCH] =?UTF-8?q?Load=20registries=20in=20core,=20wait=20them=20?= =?UTF-8?q?to=20be=20loaded=20before=20generating=20das=E2=80=A6=20(#19356?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * load registries in core, wait them to be loaded before generating dashboard * import * improve * Split out subscribe functions --- src/data/area_registry.ts | 44 ++---------------------- src/data/device_registry.ts | 41 +++------------------- src/data/entity_registry.ts | 32 ++--------------- src/data/ws-area_registry.ts | 44 ++++++++++++++++++++++++ src/data/ws-device_registry.ts | 37 ++++++++++++++++++++ src/data/ws-entity_registry_display.ts | 35 +++++++++++++++++++ src/entrypoints/core.ts | 14 +++++--- src/panels/lovelace/ha-panel-lovelace.ts | 21 ++++++++--- 8 files changed, 153 insertions(+), 115 deletions(-) create mode 100644 src/data/ws-area_registry.ts create mode 100644 src/data/ws-device_registry.ts create mode 100644 src/data/ws-entity_registry_display.ts diff --git a/src/data/area_registry.ts b/src/data/area_registry.ts index d51f7c528f77..bd0e7c97c35a 100644 --- a/src/data/area_registry.ts +++ b/src/data/area_registry.ts @@ -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 -) => - 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( - "_areaRegistry", - fetchAreaRegistry, - subscribeAreaRegistryUpdates, - conn, - onChange - ); - export const getAreaEntityLookup = ( entities: EntityRegistryEntry[] ): AreaEntityLookup => { diff --git a/src/data/device_registry.ts b/src/data/device_registry.ts index 4e2d308e0e6c..0127bdf7d383 100644 --- a/src/data/device_registry.ts +++ b/src/data/device_registry.ts @@ -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({ - type: "config/device_registry/list", - }); - -const subscribeDeviceRegistryUpdates = ( - conn: Connection, - store: Store -) => - 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( - "_dr", - fetchDeviceRegistry, - subscribeDeviceRegistryUpdates, - conn, - onChange - ); - export const sortDeviceRegistryByName = ( entries: DeviceRegistryEntry[], language: string diff --git a/src/data/entity_registry.ts b/src/data/entity_registry.ts index c55a09aaa33b..61da5aba2a73 100644 --- a/src/data/entity_registry.ts +++ b/src/data/entity_registry.ts @@ -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 -) => - 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( - "_entityRegistryDisplay", - fetchEntityRegistryDisplay, - subscribeEntityRegistryDisplayUpdates, - conn, - onChange - ); - export const sortEntityRegistryByName = ( entries: EntityRegistryEntry[], language: string diff --git a/src/data/ws-area_registry.ts b/src/data/ws-area_registry.ts new file mode 100644 index 000000000000..0f5c4a38544b --- /dev/null +++ b/src/data/ws-area_registry.ts @@ -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 +) => + 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( + "_areaRegistry", + fetchAreaRegistry, + subscribeAreaRegistryUpdates, + conn, + onChange + ); diff --git a/src/data/ws-device_registry.ts b/src/data/ws-device_registry.ts new file mode 100644 index 000000000000..85cc26568151 --- /dev/null +++ b/src/data/ws-device_registry.ts @@ -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({ + type: "config/device_registry/list", + }); + +const subscribeDeviceRegistryUpdates = ( + conn: Connection, + store: Store +) => + 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( + "_dr", + fetchDeviceRegistry, + subscribeDeviceRegistryUpdates, + conn, + onChange + ); diff --git a/src/data/ws-entity_registry_display.ts b/src/data/ws-entity_registry_display.ts new file mode 100644 index 000000000000..c57229b6189a --- /dev/null +++ b/src/data/ws-entity_registry_display.ts @@ -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 +) => + 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( + "_entityRegistryDisplay", + fetchEntityRegistryDisplay, + subscribeEntityRegistryDisplayUpdates, + conn, + onChange + ); diff --git a/src/entrypoints/core.ts b/src/entrypoints/core.ts index 6ca3c2805343..e9bf6b4c001b 100644 --- a/src/entrypoints/core.ts +++ b/src/entrypoints/core.ts @@ -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); diff --git a/src/panels/lovelace/ha-panel-lovelace.ts b/src/panels/lovelace/ha-panel-lovelace.ts index eb367df99e19..a767452e3e99 100644 --- a/src/panels/lovelace/ha-panel-lovelace.ts +++ b/src/panels/lovelace/ha-panel-lovelace.ts @@ -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!