Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 154 additions & 2 deletions src/data/automation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
} from "home-assistant-js-websocket";
import { HomeAssistant } from "../types";
import { navigate } from "../common/navigate";
import { DeviceCondition, DeviceTrigger } from "./device_automation";

export interface AutomationEntity extends HassEntityBase {
attributes: HassEntityAttributeBase & {
Expand All @@ -15,11 +16,162 @@ export interface AutomationEntity extends HassEntityBase {
export interface AutomationConfig {
alias: string;
description: string;
trigger: any[];
condition?: any[];
trigger: Trigger[];
condition?: Condition[];
action: any[];
}

export interface ForDict {
hours?: number | string;
minutes?: number | string;
seconds?: number | string;
}

export interface StateTrigger {
platform: "state";
entity_id?: string;
from?: string | number;
to?: string | number;
for?: string | number | ForDict;
}

export interface MqttTrigger {
platform: "mqtt";
topic: string;
payload?: string;
}

export interface GeoLocationTrigger {
platform: "geo_location";
source: "string";
zone: "string";
event: "enter" | "leave";
}

export interface HassTrigger {
platform: "homeassistant";
event: "start" | "shutdown";
}

export interface NumericStateTrigger {
platform: "numeric_state";
entity_id: string;
above?: number;
below?: number;
value_template?: string;
for?: string | number | ForDict;
}

export interface SunTrigger {
platform: "sun";
offset: number;
event: "sunrise" | "sunset";
}

export interface TimePatternTrigger {
platform: "time_pattern";
hours?: number | string;
minutes?: number | string;
seconds?: number | string;
}

export interface WebhookTrigger {
platform: "webhook";
webhook_id: string;
}

export interface ZoneTrigger {
platform: "zone";
entity_id: string;
zone: string;
event: "enter" | "leave";
}

export interface TimeTrigger {
platform: "time";
at: string;
}

export interface TemplateTrigger {
platform: "template";
value_template: string;
}

export interface EventTrigger {
platform: "event";
event_type: string;
event_data: any;
}

export type Trigger =
| StateTrigger
| MqttTrigger
| GeoLocationTrigger
| HassTrigger
| NumericStateTrigger
| SunTrigger
| TimePatternTrigger
| WebhookTrigger
| ZoneTrigger
| TimeTrigger
| TemplateTrigger
| EventTrigger
| DeviceTrigger;

export interface LogicalCondition {
condition: "and" | "or";
conditions: Condition[];
}

export interface StateCondition {
condition: "state";
entity_id: string;
state: string | number;
}

export interface NumericStateCondition {
condition: "numeric_state";
entity_id: string;
above?: number;
below?: number;
value_template?: string;
}

export interface SunCondition {
condition: "sun";
after_offset: number;
before_offset: number;
after: "sunrise" | "sunset";
before: "sunrise" | "sunset";
}

export interface ZoneCondition {
condition: "zone";
entity_id: string;
zone: string;
}

export interface TimeCondition {
condition: "time";
after: string;
before: string;
}

export interface TemplateCondition {
condition: "template";
value_template: string;
}

export type Condition =
| StateCondition
| NumericStateCondition
| SunCondition
| ZoneCondition
| TimeCondition
| TemplateCondition
| DeviceCondition
| LogicalCondition;

export const deleteAutomation = (hass: HomeAssistant, id: string) =>
hass.callApi("DELETE", `config/automation/config/${id}`);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox";
// tslint:disable-next-line
import { PaperListboxElement } from "@polymer/paper-listbox/paper-listbox";
import { customElement, html, LitElement, property } from "lit-element";
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-card";
import { HomeAssistant } from "../../../../types";

import "./types/ha-automation-condition-device";
import "./types/ha-automation-condition-state";
import "./types/ha-automation-condition-numeric_state";
import "./types/ha-automation-condition-sun";
import "./types/ha-automation-condition-template";
import "./types/ha-automation-condition-time";
import "./types/ha-automation-condition-zone";
import "./types/ha-automation-condition-and";
import "./types/ha-automation-condition-or";
import { Condition } from "../../../../data/automation";

const OPTIONS = [
"device",
"and",
"or",
"state",
"numeric_state",
"sun",
"template",
"time",
"zone",
];

@customElement("ha-automation-condition-editor")
export default class HaAutomationConditionEditor extends LitElement {
@property() public hass!: HomeAssistant;
@property() public condition!: Condition;
@property() public yamlMode = false;
Comment thread
bramkragten marked this conversation as resolved.

protected render() {
if (!this.condition) {
return html``;
}
const selected = OPTIONS.indexOf(this.condition.condition);
const yamlMode = this.yamlMode || selected === -1;
return html`
${yamlMode
? html`
<div style="margin-right: 24px;">
${selected === -1
? html`
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.unsupported_condition",
"condition",
this.condition.condition
)}
`
: ""}
<ha-yaml-editor
.value=${this.condition}
@value-changed=${this._onYamlChange}
></ha-yaml-editor>
</div>
`
: html`
<paper-dropdown-menu-light
.label=${this.hass.localize(
"ui.panel.config.automation.editor.conditions.type_select"
)}
no-animations
>
<paper-listbox
slot="dropdown-content"
.selected=${selected}
@iron-select=${this._typeChanged}
>
${OPTIONS.map(
(opt) => html`
<paper-item .condition=${opt}>
${this.hass.localize(
`ui.panel.config.automation.editor.conditions.type.${opt}.label`
)}
</paper-item>
`
)}
</paper-listbox>
</paper-dropdown-menu-light>
<div>
${dynamicElement(
`ha-automation-condition-${this.condition.condition}`,
{ hass: this.hass, condition: this.condition }
)}
</div>
`}
`;
}

private _typeChanged(ev: CustomEvent) {
const type = ((ev.target as PaperListboxElement)?.selectedItem as any)
?.condition;

if (!type) {
return;
}

const elClass = customElements.get(`ha-automation-condition-${type}`);

if (type !== this.condition.condition) {
fireEvent(this, "value-changed", {
value: {
condition: type,
...elClass.defaultConfig,
},
});
}
}

private _onYamlChange(ev: CustomEvent) {
ev.stopPropagation();
fireEvent(this, "value-changed", { value: ev.detail.value });
}
}

declare global {
interface HTMLElementTagNameMap {
"ha-automation-condition-editor": HaAutomationConditionEditor;
}
}
Loading