feat: Add support for template conditions (#1995)

- Closes:  #1988
This commit is contained in:
Dermot Duffy
2025-04-05 22:25:46 +01:00
committed by GitHub
parent 36783855a2
commit e7a9e20c9e
10 changed files with 184 additions and 67 deletions
+1 -2
View File
@@ -47,8 +47,7 @@ export class HASSManager {
this._hass = hass;
this._api.getConditionStateManager().setState({
state: this._hass.states,
user: this._hass.user,
hass: this._hass,
});
// Theme may depend on HASS.
+21 -8
View File
@@ -1,3 +1,4 @@
import { TemplateRenderer } from '../card-controller/templates';
import { getConfigValue } from '../config/management';
import { AdvancedCameraCardCondition } from '../config/schema/conditions/types';
import { isCompanionApp } from '../utils/companion';
@@ -23,6 +24,7 @@ export class ConditionsManager implements ConditionsManagerReadonlyInterface {
protected _listeners: ConditionsListener[] = [];
protected _mediaQueries: MediaQueryList[] = [];
protected _evaluation: ConditionsEvaluationResult = { result: false };
protected _templateRenderer: TemplateRenderer = new TemplateRenderer();
constructor(
conditions: AdvancedCameraCardCondition[],
@@ -127,8 +129,8 @@ export class ConditionsManager implements ConditionsManagerReadonlyInterface {
switch (condition.condition) {
case undefined:
case 'state': {
const fromState = oldState?.state?.[condition.entity]?.state;
const toState = newState?.state?.[condition.entity]?.state;
const fromState = oldState?.hass?.states?.[condition.entity]?.state;
const toState = newState?.hass?.states?.[condition.entity]?.state;
return {
result:
@@ -207,17 +209,18 @@ export class ConditionsManager implements ConditionsManagerReadonlyInterface {
case 'numeric_state':
return {
result:
!!newState?.state &&
condition.entity in newState.state &&
newState.state[condition.entity].state !== undefined &&
!!newState?.hass?.states &&
condition.entity in newState.hass?.states &&
newState.hass.states[condition.entity].state !== undefined &&
(condition.above === undefined ||
Number(newState.state[condition.entity].state) > condition.above) &&
Number(newState.hass.states[condition.entity].state) > condition.above) &&
(condition.below === undefined ||
Number(newState.state[condition.entity].state) < condition.below),
Number(newState.hass.states[condition.entity].state) < condition.below),
};
case 'user':
return {
result: !!newState?.user && condition.users.includes(newState.user.id),
result:
!!newState?.hass?.user && condition.users.includes(newState.hass.user.id),
};
case 'media_loaded':
return {
@@ -341,6 +344,16 @@ export class ConditionsManager implements ConditionsManagerReadonlyInterface {
).result,
};
}
case 'template':
return {
result:
!!newState?.hass &&
this._templateRenderer.renderRecursively(
newState.hass,
condition.value_template,
{ conditionState: newState },
) === true,
};
}
}
}
+2 -4
View File
@@ -1,8 +1,7 @@
import { HassEntities } from 'home-assistant-js-websocket';
import { KeysState, MicrophoneState } from '../card-controller/types';
import { ViewDisplayMode } from '../config/schema/common/display';
import { AdvancedCameraCardConfig } from '../config/schema/types';
import { CurrentUser } from '../ha/types';
import { HomeAssistant } from '../ha/types';
import { MediaLoadedInfo } from '../types';
export interface ConditionState {
@@ -16,9 +15,8 @@ export interface ConditionState {
keys?: KeysState;
mediaLoadedInfo?: MediaLoadedInfo | null;
microphone?: MicrophoneState;
state?: HassEntities;
hass?: HomeAssistant;
triggered?: Set<string>;
user?: CurrentUser;
userAgent?: string;
view?: string;
}
@@ -0,0 +1,7 @@
import { z } from 'zod';
// https://www.home-assistant.io/docs/scripts/conditions/#template-condition
export const templateConditionSchema = z.object({
condition: z.literal('template'),
value_template: z.string(),
});
+2
View File
@@ -15,6 +15,7 @@ import { viewConditionSchema } from './custom/view';
import { numericStateConditionSchema } from './stock/numeric';
import { screenConditionSchema } from './stock/screen';
import { stateConditionSchema } from './stock/state';
import { templateConditionSchema } from './stock/template';
import { usersConditionSchema } from './stock/users';
// https://www.home-assistant.io/docs/scripts/conditions/#or-condition
@@ -65,6 +66,7 @@ export const advancedCameraCardConditionSchema = z.union([
orConditionSchema,
andConditionSchema,
notConditionSchema,
templateConditionSchema,
// Custom conditions:
cameraConditionSchema,