From b71b230bfdd2b52eb54c8289e0cc96f74ce5af33 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Mon, 23 May 2022 19:08:44 -0400 Subject: [PATCH] Make entities and devices independent in the scene editor (#11046) Co-authored-by: Zack Barett Co-authored-by: Erik Co-authored-by: Paulus Schoutsen Co-authored-by: Paulus Schoutsen --- src/data/scene.ts | 5 ++ src/panels/config/scene/ha-scene-editor.ts | 55 +++++++++++++++------- src/translations/en.json | 7 ++- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/data/scene.ts b/src/data/scene.ts index f97cc2fa59..f15e7c2562 100644 --- a/src/data/scene.ts +++ b/src/data/scene.ts @@ -47,12 +47,17 @@ export interface SceneConfig { name: string; icon?: string; entities: SceneEntities; + metadata?: SceneMetaData; } export interface SceneEntities { [entityId: string]: string | { state: string; [key: string]: any }; } +export interface SceneMetaData { + [entityId: string]: { entity_only?: boolean | undefined }; +} + export const activateScene = ( hass: HomeAssistant, entityId: string diff --git a/src/panels/config/scene/ha-scene-editor.ts b/src/panels/config/scene/ha-scene-editor.ts index 5c0e8f1884..7832d9116c 100644 --- a/src/panels/config/scene/ha-scene-editor.ts +++ b/src/panels/config/scene/ha-scene-editor.ts @@ -55,6 +55,7 @@ import { SceneConfig, SceneEntities, SceneEntity, + SceneMetaData, SCENE_IGNORED_DOMAINS, showSceneEditor, } from "../../../data/scene"; @@ -628,16 +629,22 @@ export class HaSceneEditor extends SubscribeMixin( const filteredEntityReg = this._entityRegistryEntries.filter((entityReg) => this._entities.includes(entityReg.entity_id) ); - this._devices = []; + const newDevices: string[] = []; for (const entityReg of filteredEntityReg) { if (!entityReg.device_id) { continue; } - if (!this._devices.includes(entityReg.device_id)) { - this._devices = [...this._devices, entityReg.device_id]; + const entityMetaData = config.metadata?.[entityReg.entity_id]; + if ( + !newDevices.includes(entityReg.device_id) && + !entityMetaData?.entity_only + ) { + newDevices.push(entityReg.device_id); } } + + this._devices = newDevices; } private _entityPicked(ev: CustomEvent) { @@ -646,18 +653,8 @@ export class HaSceneEditor extends SubscribeMixin( if (this._entities.includes(entityId)) { return; } - const entityRegistry = this._entityRegistryEntries.find( - (entityReg) => entityReg.entity_id === entityId - ); - if ( - entityRegistry?.device_id && - !this._devices.includes(entityRegistry.device_id) - ) { - this._pickDevice(entityRegistry.device_id); - } else { - this._entities = [...this._entities, entityId]; - this._storeState(entityId); - } + this._entities = [...this._entities, entityId]; + this._storeState(entityId); this._dirty = true; } @@ -815,6 +812,28 @@ export class HaSceneEditor extends SubscribeMixin( ); } + private _calculateMetaData(): SceneMetaData { + const output: SceneMetaData = {}; + + for (const entityReg of this._entityRegistryEntries) { + if (!this._entities.includes(entityReg.entity_id)) { + continue; + } + + const entityState = this._getCurrentState(entityReg.entity_id); + + if (!entityState) { + continue; + } + + output[entityReg.entity_id] = { + entity_only: !this._devices.includes(entityReg.device_id!), + }; + } + + return output; + } + private _calculateStates(): SceneEntities { const output: SceneEntities = {}; this._entities.forEach((entityId) => { @@ -847,7 +866,11 @@ export class HaSceneEditor extends SubscribeMixin( private async _saveScene(): Promise { const id = !this.sceneId ? "" + Date.now() : this.sceneId!; - this._config = { ...this._config!, entities: this._calculateStates() }; + this._config = { + ...this._config!, + entities: this._calculateStates(), + metadata: this._calculateMetaData(), + }; try { this._saving = true; await saveScene(this.hass, id, this._config); diff --git a/src/translations/en.json b/src/translations/en.json index 63010bcb35..824a63d04e 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2257,15 +2257,14 @@ "area": "Area", "devices": { "header": "Devices", - "introduction": "Add the devices that you want to be included in your scene. Set all the devices to the state you want for this scene.", + "introduction": "Add the devices that you want to be included in your scene. Set all entities in each device to the state you want for this scene.", "add": "Add a device", "delete": "Delete device" }, "entities": { "header": "Entities", - "introduction": "Entities that do not belong to a device can be set here.", - "without_device": "Entities without device", - "device_entities": "If you add an entity that belongs to a device, the device will be added.", + "introduction": "Individual entities can be added here.", + "without_device": "Entities", "add": "Add an entity", "delete": "Delete entity" }