Skip to content

Commit

Permalink
Fix device integration filter for entityless devices (#21136)
Browse files Browse the repository at this point in the history
* Fix device integration filter for entityless devices

* code review
  • Loading branch information
karwosts authored Jun 27, 2024
1 parent b2a55dd commit 7aa005e
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 11 deletions.
13 changes: 12 additions & 1 deletion src/components/ha-selector/ha-selector-area.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;

Expand Down
13 changes: 12 additions & 1 deletion src/components/ha-selector/ha-selector-device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;

Expand Down
13 changes: 12 additions & 1 deletion src/components/ha-selector/ha-selector-floor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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;

Expand Down
27 changes: 21 additions & 6 deletions src/data/device_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
EntityRegistryDisplayEntry,
EntityRegistryEntry,
} from "./entity_registry";
import { ConfigEntry } from "./config_entries";
import type { EntitySources } from "./entity_sources";

export {
Expand Down Expand Up @@ -142,20 +143,34 @@ export const getDeviceEntityDisplayLookup = (

export const getDeviceIntegrationLookup = (
entitySources: EntitySources,
entities: EntityRegistryDisplayEntry[] | EntityRegistryEntry[]
): Record<string, string[]> => {
const deviceIntegrations: Record<string, string[]> = {};
entities: EntityRegistryDisplayEntry[] | EntityRegistryEntry[],
devices?: DeviceRegistryEntry[],
configEntries?: ConfigEntry[]
): Record<string, Set<string>> => {
const deviceIntegrations: Record<string, Set<string>> = {};

for (const entity of entities) {
const source = entitySources[entity.entity_id];
if (!source?.domain || entity.device_id === null) {
continue;
}

if (!deviceIntegrations[entity.device_id!]) {
deviceIntegrations[entity.device_id!] = [];
deviceIntegrations[entity.device_id!] =
deviceIntegrations[entity.device_id!] || new Set<string>();
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<string>();
deviceIntegrations[device.id].add(entry.domain);
}
}
}
deviceIntegrations[entity.device_id!].push(source.domain);
}
return deviceIntegrations;
};
4 changes: 2 additions & 2 deletions src/data/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ export const entityMeetsTargetSelector = (
export const filterSelectorDevices = (
filterDevice: DeviceSelectorFilter,
device: DeviceRegistryEntry,
deviceIntegrationLookup?: Record<string, string[]> | undefined
deviceIntegrationLookup?: Record<string, Set<string>> | undefined
): boolean => {
const {
manufacturer: filterManufacturer,
Expand All @@ -713,7 +713,7 @@ export const filterSelectorDevices = (
}

if (filterIntegration && deviceIntegrationLookup) {
if (!deviceIntegrationLookup?.[device.id]?.includes(filterIntegration)) {
if (!deviceIntegrationLookup?.[device.id]?.has(filterIntegration)) {
return false;
}
}
Expand Down

0 comments on commit 7aa005e

Please sign in to comment.