407 lines
9.1 KiB
TypeScript
407 lines
9.1 KiB
TypeScript
import {
|
|
HassEntityAttributeBase,
|
|
HassEntityBase,
|
|
} from "home-assistant-js-websocket";
|
|
import { navigate } from "../common/navigate";
|
|
import { Context, HomeAssistant } from "../types";
|
|
import { BlueprintInput } from "./blueprint";
|
|
import { DeviceCondition, DeviceTrigger } from "./device_automation";
|
|
import { Action, MODES } from "./script";
|
|
|
|
export const AUTOMATION_DEFAULT_MODE: (typeof MODES)[number] = "single";
|
|
export const AUTOMATION_DEFAULT_MAX = 10;
|
|
|
|
export interface AutomationEntity extends HassEntityBase {
|
|
attributes: HassEntityAttributeBase & {
|
|
id?: string;
|
|
last_triggered: string;
|
|
};
|
|
}
|
|
|
|
export type AutomationConfig =
|
|
| ManualAutomationConfig
|
|
| BlueprintAutomationConfig;
|
|
|
|
export interface ManualAutomationConfig {
|
|
id?: string;
|
|
alias?: string;
|
|
description?: string;
|
|
trigger: Trigger | Trigger[];
|
|
condition?: Condition | Condition[];
|
|
action: Action | Action[];
|
|
mode?: (typeof MODES)[number];
|
|
max?: number;
|
|
max_exceeded?:
|
|
| "silent"
|
|
| "critical"
|
|
| "fatal"
|
|
| "error"
|
|
| "warning"
|
|
| "warn"
|
|
| "info"
|
|
| "debug"
|
|
| "notset";
|
|
variables?: Record<string, unknown>;
|
|
}
|
|
|
|
export interface BlueprintAutomationConfig extends ManualAutomationConfig {
|
|
use_blueprint: { path: string; input?: BlueprintInput };
|
|
}
|
|
|
|
export interface ForDict {
|
|
days?: number;
|
|
hours?: number;
|
|
minutes?: number;
|
|
seconds?: number;
|
|
milliseconds?: number;
|
|
}
|
|
|
|
export interface ContextConstraint {
|
|
context_id?: string;
|
|
parent_id?: string;
|
|
user_id?: string | string[];
|
|
}
|
|
|
|
export interface BaseTrigger {
|
|
alias?: string;
|
|
platform: string;
|
|
id?: string;
|
|
variables?: Record<string, unknown>;
|
|
enabled?: boolean;
|
|
}
|
|
|
|
export interface StateTrigger extends BaseTrigger {
|
|
platform: "state";
|
|
entity_id: string | string[];
|
|
attribute?: string;
|
|
from?: string | string[];
|
|
to?: string | string[];
|
|
for?: string | number | ForDict;
|
|
}
|
|
|
|
export interface MqttTrigger extends BaseTrigger {
|
|
platform: "mqtt";
|
|
topic: string;
|
|
payload?: string;
|
|
}
|
|
|
|
export interface GeoLocationTrigger extends BaseTrigger {
|
|
platform: "geo_location";
|
|
source: string;
|
|
zone: string;
|
|
event: "enter" | "leave";
|
|
}
|
|
|
|
export interface HassTrigger extends BaseTrigger {
|
|
platform: "homeassistant";
|
|
event: "start" | "shutdown";
|
|
}
|
|
|
|
export interface NumericStateTrigger extends BaseTrigger {
|
|
platform: "numeric_state";
|
|
entity_id: string | string[];
|
|
attribute?: string;
|
|
above?: number;
|
|
below?: number;
|
|
value_template?: string;
|
|
for?: string | number | ForDict;
|
|
}
|
|
|
|
export interface ConversationTrigger extends BaseTrigger {
|
|
platform: "conversation";
|
|
command: string | string[];
|
|
}
|
|
|
|
export interface SunTrigger extends BaseTrigger {
|
|
platform: "sun";
|
|
offset: number;
|
|
event: "sunrise" | "sunset";
|
|
}
|
|
|
|
export interface TimePatternTrigger extends BaseTrigger {
|
|
platform: "time_pattern";
|
|
hours?: number | string;
|
|
minutes?: number | string;
|
|
seconds?: number | string;
|
|
}
|
|
|
|
export interface WebhookTrigger extends BaseTrigger {
|
|
platform: "webhook";
|
|
webhook_id: string;
|
|
allowed_methods?: string[];
|
|
local_only?: boolean;
|
|
}
|
|
|
|
export interface PersistentNotificationTrigger extends BaseTrigger {
|
|
platform: "persistent_notification";
|
|
notification_id?: string;
|
|
update_type?: string[];
|
|
}
|
|
|
|
export interface ZoneTrigger extends BaseTrigger {
|
|
platform: "zone";
|
|
entity_id: string;
|
|
zone: string;
|
|
event: "enter" | "leave";
|
|
}
|
|
|
|
export interface TagTrigger extends BaseTrigger {
|
|
platform: "tag";
|
|
tag_id: string;
|
|
device_id?: string;
|
|
}
|
|
|
|
export interface TimeTrigger extends BaseTrigger {
|
|
platform: "time";
|
|
at: string;
|
|
}
|
|
|
|
export interface TemplateTrigger extends BaseTrigger {
|
|
platform: "template";
|
|
value_template: string;
|
|
for?: string | number | ForDict;
|
|
}
|
|
|
|
export interface EventTrigger extends BaseTrigger {
|
|
platform: "event";
|
|
event_type: string;
|
|
event_data?: any;
|
|
context?: ContextConstraint;
|
|
}
|
|
|
|
export interface CalendarTrigger extends BaseTrigger {
|
|
platform: "calendar";
|
|
event: "start" | "end";
|
|
entity_id: string;
|
|
offset: string;
|
|
}
|
|
|
|
export type Trigger =
|
|
| StateTrigger
|
|
| MqttTrigger
|
|
| GeoLocationTrigger
|
|
| HassTrigger
|
|
| NumericStateTrigger
|
|
| SunTrigger
|
|
| ConversationTrigger
|
|
| TimePatternTrigger
|
|
| WebhookTrigger
|
|
| PersistentNotificationTrigger
|
|
| ZoneTrigger
|
|
| TagTrigger
|
|
| TimeTrigger
|
|
| TemplateTrigger
|
|
| EventTrigger
|
|
| DeviceTrigger
|
|
| CalendarTrigger;
|
|
|
|
interface BaseCondition {
|
|
condition: string;
|
|
alias?: string;
|
|
enabled?: boolean;
|
|
}
|
|
|
|
export interface LogicalCondition extends BaseCondition {
|
|
condition: "and" | "not" | "or";
|
|
conditions: Condition | Condition[];
|
|
}
|
|
|
|
export interface StateCondition extends BaseCondition {
|
|
condition: "state";
|
|
entity_id: string;
|
|
attribute?: string;
|
|
state: string | number | string[];
|
|
for?: string | number | ForDict;
|
|
match?: "all" | "any";
|
|
}
|
|
|
|
export interface NumericStateCondition extends BaseCondition {
|
|
condition: "numeric_state";
|
|
entity_id: string;
|
|
attribute?: string;
|
|
above?: string | number;
|
|
below?: string | number;
|
|
value_template?: string;
|
|
}
|
|
|
|
export interface SunCondition extends BaseCondition {
|
|
condition: "sun";
|
|
after_offset?: number;
|
|
before_offset?: number;
|
|
after?: "sunrise" | "sunset";
|
|
before?: "sunrise" | "sunset";
|
|
}
|
|
|
|
export interface ZoneCondition extends BaseCondition {
|
|
condition: "zone";
|
|
entity_id: string;
|
|
zone: string;
|
|
}
|
|
|
|
type Weekday = "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat";
|
|
|
|
export interface TimeCondition extends BaseCondition {
|
|
condition: "time";
|
|
after?: string;
|
|
before?: string;
|
|
weekday?: Weekday | Weekday[];
|
|
}
|
|
|
|
export interface TemplateCondition extends BaseCondition {
|
|
condition: "template";
|
|
value_template: string;
|
|
}
|
|
|
|
export interface TriggerCondition extends BaseCondition {
|
|
condition: "trigger";
|
|
id: string;
|
|
}
|
|
|
|
type ShorthandBaseCondition = Omit<BaseCondition, "condition">;
|
|
|
|
export interface ShorthandAndConditionList extends ShorthandBaseCondition {
|
|
condition: Condition[];
|
|
}
|
|
|
|
export interface ShorthandAndCondition extends ShorthandBaseCondition {
|
|
and: Condition[];
|
|
}
|
|
|
|
export interface ShorthandOrCondition extends ShorthandBaseCondition {
|
|
or: Condition[];
|
|
}
|
|
|
|
export interface ShorthandNotCondition extends ShorthandBaseCondition {
|
|
not: Condition[];
|
|
}
|
|
|
|
export interface AutomationElementGroup {
|
|
[key: string]: { icon?: string; members?: AutomationElementGroup };
|
|
}
|
|
|
|
export type Condition =
|
|
| StateCondition
|
|
| NumericStateCondition
|
|
| SunCondition
|
|
| ZoneCondition
|
|
| TimeCondition
|
|
| TemplateCondition
|
|
| DeviceCondition
|
|
| LogicalCondition
|
|
| TriggerCondition;
|
|
|
|
export type ConditionWithShorthand =
|
|
| Condition
|
|
| ShorthandAndConditionList
|
|
| ShorthandAndCondition
|
|
| ShorthandOrCondition
|
|
| ShorthandNotCondition;
|
|
|
|
export const expandConditionWithShorthand = (
|
|
cond: ConditionWithShorthand
|
|
): Condition => {
|
|
if ("condition" in cond && Array.isArray(cond.condition)) {
|
|
return {
|
|
condition: "and",
|
|
conditions: cond.condition,
|
|
};
|
|
}
|
|
|
|
for (const condition of ["and", "or", "not"]) {
|
|
if (condition in cond) {
|
|
return {
|
|
condition,
|
|
conditions: cond[condition],
|
|
} as Condition;
|
|
}
|
|
}
|
|
|
|
return cond as Condition;
|
|
};
|
|
|
|
export const triggerAutomationActions = (
|
|
hass: HomeAssistant,
|
|
entityId: string
|
|
) => {
|
|
hass.callService("automation", "trigger", {
|
|
entity_id: entityId,
|
|
skip_condition: true,
|
|
});
|
|
};
|
|
|
|
export const deleteAutomation = (hass: HomeAssistant, id: string) =>
|
|
hass.callApi("DELETE", `config/automation/config/${id}`);
|
|
|
|
let initialAutomationEditorData: Partial<AutomationConfig> | undefined;
|
|
|
|
export const fetchAutomationFileConfig = (hass: HomeAssistant, id: string) =>
|
|
hass.callApi<AutomationConfig>("GET", `config/automation/config/${id}`);
|
|
|
|
export const getAutomationStateConfig = (
|
|
hass: HomeAssistant,
|
|
entity_id: string
|
|
) =>
|
|
hass.callWS<{ config: AutomationConfig }>({
|
|
type: "automation/config",
|
|
entity_id,
|
|
});
|
|
|
|
export const saveAutomationConfig = (
|
|
hass: HomeAssistant,
|
|
id: string,
|
|
config: AutomationConfig
|
|
) => hass.callApi<void>("POST", `config/automation/config/${id}`, config);
|
|
|
|
export const showAutomationEditor = (data?: Partial<AutomationConfig>) => {
|
|
initialAutomationEditorData = data;
|
|
navigate("/config/automation/edit/new");
|
|
};
|
|
|
|
export const duplicateAutomation = (config: AutomationConfig) => {
|
|
showAutomationEditor({
|
|
...config,
|
|
id: undefined,
|
|
alias: undefined,
|
|
});
|
|
};
|
|
|
|
export const getAutomationEditorInitData = () => {
|
|
const data = initialAutomationEditorData;
|
|
initialAutomationEditorData = undefined;
|
|
return data;
|
|
};
|
|
|
|
export const subscribeTrigger = (
|
|
hass: HomeAssistant,
|
|
onChange: (result: {
|
|
variables: {
|
|
trigger: Record<string, unknown>;
|
|
};
|
|
context: Context;
|
|
}) => void,
|
|
trigger: Trigger | Trigger[],
|
|
variables?: Record<string, unknown>
|
|
) =>
|
|
hass.connection.subscribeMessage(onChange, {
|
|
type: "subscribe_trigger",
|
|
trigger,
|
|
variables,
|
|
});
|
|
|
|
export const testCondition = (
|
|
hass: HomeAssistant,
|
|
condition: Condition | Condition[],
|
|
variables?: Record<string, unknown>
|
|
) =>
|
|
hass.callWS<{ result: boolean }>({
|
|
type: "test_condition",
|
|
condition,
|
|
variables,
|
|
});
|
|
|
|
export type AutomationClipboard = {
|
|
trigger?: Trigger;
|
|
condition?: Condition;
|
|
action?: Action;
|
|
};
|