Add scene domain and associated tap-action (#164)

Scenes are added as a domain so they're available at the top navigation 
bar.
The view doesn't have controller cards since switching multiple scenes 
at once makes no sense.

---------

Co-authored-by: DigiLive <github@digilive.nl>
This commit is contained in:
w531t4
2025-03-08 02:25:17 -05:00
committed by GitHub
parent c6d475e41f
commit d1456426de
7 changed files with 143 additions and 1 deletions

View File

@ -365,6 +365,17 @@ class Helper {
return states;
}
/**
* Get the state object of a HASS entity.
*
* @param {EntityRegistryEntry} entity The entity for which to get the state.
* @returns {HassEntity | undefined} The state object of the entity, or undefined if not found.
* @static
*/
static getEntityState(entity: EntityRegistryEntry): HassEntity | undefined {
return this.#hassStates[entity.entity_id];
}
/**
* Sanitize a classname.
*

63
src/cards/SceneCard.ts Normal file
View File

@ -0,0 +1,63 @@
import {AbstractCard} from "./AbstractCard";
import {cards} from "../types/strategy/cards";
import {EntityRegistryEntry} from "../types/homeassistant/data/entity_registry";
import {generic} from "../types/strategy/generic";
import {EntityCardConfig} from "../types/lovelace-mushroom/cards/entity-card-config";
import {Helper} from "../Helper";
import isCallServiceActionConfig = generic.isCallServiceActionConfig;
import isCallServiceActionTarget = generic.isCallServiceActionTarget;
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
/**
* Scene Card Class
*
* Used to create a card for an entity of the scene domain.
*
* @class
* @extends AbstractCard
*/
class SceneCard extends AbstractCard {
/**
* Default configuration of the card.
*
* @type {EntityCardConfig}
* @private
*/
#defaultConfig: EntityCardConfig = {
type: "custom:mushroom-entity-card",
icon: "mdi:palette",
icon_color: "blue",
tap_action: {
action: "call-service",
service: "scene.turn_on",
target: {
entity_id: undefined,
},
},
};
/**
* Class constructor.
*
* @param {EntityRegistryEntry} entity The hass entity to create a card for.
* @param {cards.EntityCardOptions} [options={}] Options for the card.
* @throws {Error} If the Helper module isn't initialized.
*/
constructor(entity: EntityRegistryEntry, options: cards.EntityCardOptions = {}) {
super(entity);
// Set the target for tap action.
if (
isCallServiceActionConfig(this.#defaultConfig.tap_action)
&& isCallServiceActionTarget(this.#defaultConfig.tap_action.target)
) {
this.#defaultConfig.tap_action.target.entity_id = entity.entity_id;
}
this.#defaultConfig.icon = Helper.getEntityState(entity)?.attributes.icon ?? this.#defaultConfig.icon;
this.config = Object.assign(this.config, this.#defaultConfig, options);
}
}
export {SceneCard};

View File

@ -37,6 +37,12 @@ export const getConfigurationDefaults = (localize: Function): StrategyDefaults =
offService: "light.turn_off",
hidden: false,
},
scene: {
title: localize("scene.scenes"),
showControls: false,
onService: "scene.turn_on",
hidden: false,
},
fan: {
title: localize("fan.fans"),
showControls: true,
@ -151,6 +157,10 @@ export const getConfigurationDefaults = (localize: Function): StrategyDefaults =
order: 8,
hidden: false,
},
scene: {
order: 9,
hidden: false,
},
}
};
};

View File

@ -44,6 +44,9 @@
"media_player": {
"media_players": "Mediaplayers"
},
"scene": {
"scenes": "Scenes"
},
"select": {
"selects": "Selects"
},

View File

@ -44,6 +44,9 @@
"media_player": {
"media_players": "Mediaspelers"
},
"scene": {
"scenes": "Scenes"
},
"select": {
"selects": "Statuslijsten"
},

View File

@ -123,7 +123,7 @@ abstract class AbstractView {
}
// Add a Controller Card for all the entities in the view.
if (viewCards.length) {
if (this.viewControllerCard.cards.length && viewCards.length) {
viewCards.unshift(this.viewControllerCard);
}

52
src/views/SceneView.ts Normal file
View File

@ -0,0 +1,52 @@
import {Helper} from "../Helper";
import {AbstractView} from "./AbstractView";
import {views} from "../types/strategy/views";
// noinspection JSUnusedGlobalSymbols Class is dynamically imported.
/**
* Scene View Class.
*
* Used to create a view for entities of the scene domain.
*
* @class SceneView
* @extends AbstractView
*/
class SceneView extends AbstractView {
/**
* Domain of the view's entities.
*
* @type {string}
* @static
* @private
*/
static #domain: string = "scene";
/**
* Default configuration of the view.
*
* @type {views.ViewConfig}
* @private
*/
#defaultConfig: views.ViewConfig = {
title: Helper.customLocalize("scene.scenes"),
path: "scenes",
icon: "mdi:palette",
subview: false,
controllerCardOptions: {
showControls: false,
},
};
/**
* Class constructor.
*
* @param {views.ViewConfig} [options={}] Options for the view.
*/
constructor(options: views.ViewConfig = {}) {
super(SceneView.#domain);
this.config = Object.assign(this.config, this.#defaultConfig, options);
}
}
export {SceneView};