diff --git a/src/components/ha-selector/ha-selector-area.ts b/src/components/ha-selector/ha-selector-area.ts index 7690c387adfd..47230ff88d11 100644 --- a/src/components/ha-selector/ha-selector-area.ts +++ b/src/components/ha-selector/ha-selector-area.ts @@ -11,6 +11,7 @@ import { fetchEntitySourcesWithCache, } from "../../data/entity_sources"; import type { AreaSelector } from "../../data/selector"; +import { ConfigEntry, getConfigEntries } from "../../data/config_entries"; import { filterSelectorDevices, filterSelectorEntities, @@ -37,6 +38,8 @@ export class HaAreaSelector extends LitElement { @state() private _entitySources?: EntitySources; + @state() private _configEntries?: ConfigEntry[]; + private _deviceIntegrationLookup = memoizeOne(getDeviceIntegrationLookup); private _hasIntegration(selector: AreaSelector) { @@ -72,6 +75,12 @@ export class HaAreaSelector extends LitElement { this._entitySources = sources; }); } + if (!this._configEntries && this._hasIntegration(this.selector)) { + this._configEntries = []; + getConfigEntries(this.hass).then((entries) => { + this._configEntries = entries; + }); + } } protected render() { @@ -136,7 +145,9 @@ export class HaAreaSelector extends LitElement { const deviceIntegrations = this._entitySources ? this._deviceIntegrationLookup( this._entitySources, - Object.values(this.hass.entities) + Object.values(this.hass.entities), + Object.values(this.hass.devices), + this._configEntries ) : undefined; diff --git a/src/components/ha-selector/ha-selector-device.ts b/src/components/ha-selector/ha-selector-device.ts index b3ffebd4b667..0131b9b69854 100644 --- a/src/components/ha-selector/ha-selector-device.ts +++ b/src/components/ha-selector/ha-selector-device.ts @@ -11,6 +11,7 @@ import { fetchEntitySourcesWithCache, } from "../../data/entity_sources"; import type { DeviceSelector } from "../../data/selector"; +import { ConfigEntry, getConfigEntries } from "../../data/config_entries"; import { filterSelectorDevices, filterSelectorEntities, @@ -27,6 +28,8 @@ export class HaDeviceSelector extends LitElement { @state() private _entitySources?: EntitySources; + @state() private _configEntries?: ConfigEntry[]; + @property() public value?: any; @property() public label?: string; @@ -75,6 +78,12 @@ export class HaDeviceSelector extends LitElement { this._entitySources = sources; }); } + if (!this._configEntries && this._hasIntegration(this.selector)) { + this._configEntries = []; + getConfigEntries(this.hass).then((entries) => { + this._configEntries = entries; + }); + } } protected render() { @@ -123,7 +132,9 @@ export class HaDeviceSelector extends LitElement { const deviceIntegrations = this._entitySources ? this._deviceIntegrationLookup( this._entitySources, - Object.values(this.hass.entities) + Object.values(this.hass.entities), + Object.values(this.hass.devices), + this._configEntries ) : undefined; diff --git a/src/components/ha-selector/ha-selector-floor.ts b/src/components/ha-selector/ha-selector-floor.ts index eac63f414edb..6d4d0d29c834 100644 --- a/src/components/ha-selector/ha-selector-floor.ts +++ b/src/components/ha-selector/ha-selector-floor.ts @@ -11,6 +11,7 @@ import { fetchEntitySourcesWithCache, } from "../../data/entity_sources"; import type { FloorSelector } from "../../data/selector"; +import { ConfigEntry, getConfigEntries } from "../../data/config_entries"; import { filterSelectorDevices, filterSelectorEntities, @@ -37,6 +38,8 @@ export class HaFloorSelector extends LitElement { @state() private _entitySources?: EntitySources; + @state() private _configEntries?: ConfigEntry[]; + private _deviceIntegrationLookup = memoizeOne(getDeviceIntegrationLookup); private _hasIntegration(selector: FloorSelector) { @@ -72,6 +75,12 @@ export class HaFloorSelector extends LitElement { this._entitySources = sources; }); } + if (!this._configEntries && this._hasIntegration(this.selector)) { + this._configEntries = []; + getConfigEntries(this.hass).then((entries) => { + this._configEntries = entries; + }); + } } protected render() { @@ -136,7 +145,9 @@ export class HaFloorSelector extends LitElement { const deviceIntegrations = this._entitySources ? this._deviceIntegrationLookup( this._entitySources, - Object.values(this.hass.entities) + Object.values(this.hass.entities), + Object.values(this.hass.devices), + this._configEntries ) : undefined; diff --git a/src/data/device_registry.ts b/src/data/device_registry.ts index 80e9a5b05373..90bd894e8a62 100644 --- a/src/data/device_registry.ts +++ b/src/data/device_registry.ts @@ -5,6 +5,7 @@ import type { EntityRegistryDisplayEntry, EntityRegistryEntry, } from "./entity_registry"; +import { ConfigEntry } from "./config_entries"; import type { EntitySources } from "./entity_sources"; export { @@ -142,9 +143,11 @@ export const getDeviceEntityDisplayLookup = ( export const getDeviceIntegrationLookup = ( entitySources: EntitySources, - entities: EntityRegistryDisplayEntry[] | EntityRegistryEntry[] -): Record => { - const deviceIntegrations: Record = {}; + entities: EntityRegistryDisplayEntry[] | EntityRegistryEntry[], + devices?: DeviceRegistryEntry[], + configEntries?: ConfigEntry[] +): Record> => { + const deviceIntegrations: Record> = {}; for (const entity of entities) { const source = entitySources[entity.entity_id]; @@ -152,10 +155,22 @@ export const getDeviceIntegrationLookup = ( continue; } - if (!deviceIntegrations[entity.device_id!]) { - deviceIntegrations[entity.device_id!] = []; + deviceIntegrations[entity.device_id!] = + deviceIntegrations[entity.device_id!] || new Set(); + deviceIntegrations[entity.device_id!].add(source.domain); + } + // Lookup devices that have no entities + if (devices && configEntries) { + for (const device of devices) { + for (const config_entry_id of device.config_entries) { + const entry = configEntries.find((e) => e.entry_id === config_entry_id); + if (entry?.domain) { + deviceIntegrations[device.id] = + deviceIntegrations[device.id] || new Set(); + deviceIntegrations[device.id].add(entry.domain); + } + } } - deviceIntegrations[entity.device_id!].push(source.domain); } return deviceIntegrations; }; diff --git a/src/data/selector.ts b/src/data/selector.ts index bb90c792f48b..60b9e4973b1c 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -696,7 +696,7 @@ export const entityMeetsTargetSelector = ( export const filterSelectorDevices = ( filterDevice: DeviceSelectorFilter, device: DeviceRegistryEntry, - deviceIntegrationLookup?: Record | undefined + deviceIntegrationLookup?: Record> | undefined ): boolean => { const { manufacturer: filterManufacturer, @@ -713,7 +713,7 @@ export const filterSelectorDevices = ( } if (filterIntegration && deviceIntegrationLookup) { - if (!deviceIntegrationLookup?.[device.id]?.includes(filterIntegration)) { + if (!deviceIntegrationLookup?.[device.id]?.has(filterIntegration)) { return false; } }