Skip to content

Commit 8dd35cb

Browse files
emontnemeryabmantisarturpragaczbramkragtenfrenck
authored
Add entity triggers and conditions (home-assistant#156852)
Co-authored-by: Abílio Costa <[email protected]> Co-authored-by: Artur Pragacz <[email protected]> Co-authored-by: abmantis <[email protected]> Co-authored-by: Bram Kragten <[email protected]> Co-authored-by: Franck Nijhof <[email protected]> Co-authored-by: Martin Hjelmare <[email protected]>
1 parent 6fa971d commit 8dd35cb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+4736
-16
lines changed

homeassistant/components/alarm_control_panel/icons.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,28 @@
3636
"alarm_trigger": {
3737
"service": "mdi:bell-ring"
3838
}
39+
},
40+
"triggers": {
41+
"armed": {
42+
"trigger": "mdi:shield"
43+
},
44+
"armed_away": {
45+
"trigger": "mdi:shield-lock"
46+
},
47+
"armed_home": {
48+
"trigger": "mdi:shield-home"
49+
},
50+
"armed_night": {
51+
"trigger": "mdi:shield-moon"
52+
},
53+
"armed_vacation": {
54+
"trigger": "mdi:shield-airplane"
55+
},
56+
"disarmed": {
57+
"trigger": "mdi:shield-off"
58+
},
59+
"triggered": {
60+
"trigger": "mdi:bell-ring"
61+
}
3962
}
4063
}

homeassistant/components/alarm_control_panel/strings.json

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2+
"common": {
3+
"trigger_behavior_description": "The behavior of the targeted alarms to trigger on.",
4+
"trigger_behavior_name": "Behavior"
5+
},
26
"device_automation": {
37
"action_type": {
48
"arm_away": "Arm {entity_name} away",
@@ -71,6 +75,15 @@
7175
"message": "Arming requires a code but none was given for {entity_id}."
7276
}
7377
},
78+
"selector": {
79+
"trigger_behavior": {
80+
"options": {
81+
"any": "Any",
82+
"first": "First",
83+
"last": "Last"
84+
}
85+
}
86+
},
7487
"services": {
7588
"alarm_arm_away": {
7689
"description": "Arms the alarm in the away mode.",
@@ -143,5 +156,84 @@
143156
"name": "Trigger"
144157
}
145158
},
146-
"title": "Alarm control panel"
159+
"title": "Alarm control panel",
160+
"triggers": {
161+
"armed": {
162+
"description": "Triggers when an alarm is armed.",
163+
"description_configured": "[%key:component::alarm_control_panel::triggers::armed::description%]",
164+
"fields": {
165+
"behavior": {
166+
"description": "[%key:component::alarm_control_panel::common::trigger_behavior_description%]",
167+
"name": "[%key:component::alarm_control_panel::common::trigger_behavior_name%]"
168+
}
169+
},
170+
"name": "When an alarm is armed"
171+
},
172+
"armed_away": {
173+
"description": "Triggers when an alarm is armed away.",
174+
"description_configured": "[%key:component::alarm_control_panel::triggers::armed_away::description%]",
175+
"fields": {
176+
"behavior": {
177+
"description": "[%key:component::alarm_control_panel::common::trigger_behavior_description%]",
178+
"name": "[%key:component::alarm_control_panel::common::trigger_behavior_name%]"
179+
}
180+
},
181+
"name": "When an alarm is armed away"
182+
},
183+
"armed_home": {
184+
"description": "Triggers when an alarm is armed home.",
185+
"description_configured": "[%key:component::alarm_control_panel::triggers::armed_home::description%]",
186+
"fields": {
187+
"behavior": {
188+
"description": "[%key:component::alarm_control_panel::common::trigger_behavior_description%]",
189+
"name": "[%key:component::alarm_control_panel::common::trigger_behavior_name%]"
190+
}
191+
},
192+
"name": "When an alarm is armed home"
193+
},
194+
"armed_night": {
195+
"description": "Triggers when an alarm is armed night.",
196+
"description_configured": "[%key:component::alarm_control_panel::triggers::armed_night::description%]",
197+
"fields": {
198+
"behavior": {
199+
"description": "[%key:component::alarm_control_panel::common::trigger_behavior_description%]",
200+
"name": "[%key:component::alarm_control_panel::common::trigger_behavior_name%]"
201+
}
202+
},
203+
"name": "When an alarm is armed night"
204+
},
205+
"armed_vacation": {
206+
"description": "Triggers when an alarm is armed vacation.",
207+
"description_configured": "[%key:component::alarm_control_panel::triggers::armed_vacation::description%]",
208+
"fields": {
209+
"behavior": {
210+
"description": "[%key:component::alarm_control_panel::common::trigger_behavior_description%]",
211+
"name": "[%key:component::alarm_control_panel::common::trigger_behavior_name%]"
212+
}
213+
},
214+
"name": "When an alarm is armed vacation"
215+
},
216+
"disarmed": {
217+
"description": "Triggers when an alarm is disarmed.",
218+
"description_configured": "[%key:component::alarm_control_panel::triggers::disarmed::description%]",
219+
"fields": {
220+
"behavior": {
221+
"description": "[%key:component::alarm_control_panel::common::trigger_behavior_description%]",
222+
"name": "[%key:component::alarm_control_panel::common::trigger_behavior_name%]"
223+
}
224+
},
225+
"name": "When an alarm is disarmed"
226+
},
227+
"triggered": {
228+
"description": "Triggers when an alarm is triggered.",
229+
"description_configured": "[%key:component::alarm_control_panel::triggers::triggered::description%]",
230+
"fields": {
231+
"behavior": {
232+
"description": "[%key:component::alarm_control_panel::common::trigger_behavior_description%]",
233+
"name": "[%key:component::alarm_control_panel::common::trigger_behavior_name%]"
234+
}
235+
},
236+
"name": "When an alarm is triggered"
237+
}
238+
}
147239
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
"""Provides triggers for alarm control panels."""
2+
3+
from homeassistant.core import HomeAssistant
4+
from homeassistant.exceptions import HomeAssistantError
5+
from homeassistant.helpers.entity import get_supported_features
6+
from homeassistant.helpers.trigger import (
7+
EntityStateTriggerBase,
8+
Trigger,
9+
make_conditional_entity_state_trigger,
10+
make_entity_state_trigger,
11+
)
12+
13+
from .const import DOMAIN, AlarmControlPanelEntityFeature, AlarmControlPanelState
14+
15+
16+
def supports_feature(hass: HomeAssistant, entity_id: str, features: int) -> bool:
17+
"""Get the device class of an entity or UNDEFINED if not found."""
18+
try:
19+
return bool(get_supported_features(hass, entity_id) & features)
20+
except HomeAssistantError:
21+
return False
22+
23+
24+
class EntityStateTriggerRequiredFeatures(EntityStateTriggerBase):
25+
"""Trigger for entity state changes."""
26+
27+
_required_features: int
28+
29+
def entity_filter(self, entities: set[str]) -> set[str]:
30+
"""Filter entities of this domain."""
31+
entities = super().entity_filter(entities)
32+
return {
33+
entity_id
34+
for entity_id in entities
35+
if supports_feature(self._hass, entity_id, self._required_features)
36+
}
37+
38+
39+
def make_entity_state_trigger_required_features(
40+
domain: str, to_state: str, required_features: int
41+
) -> type[EntityStateTriggerBase]:
42+
"""Create an entity state trigger class."""
43+
44+
class CustomTrigger(EntityStateTriggerRequiredFeatures):
45+
"""Trigger for entity state changes."""
46+
47+
_domain = domain
48+
_to_state = to_state
49+
_required_features = required_features
50+
51+
return CustomTrigger
52+
53+
54+
TRIGGERS: dict[str, type[Trigger]] = {
55+
"armed": make_conditional_entity_state_trigger(
56+
DOMAIN,
57+
from_states={
58+
AlarmControlPanelState.ARMING,
59+
AlarmControlPanelState.DISARMED,
60+
AlarmControlPanelState.DISARMING,
61+
AlarmControlPanelState.PENDING,
62+
AlarmControlPanelState.TRIGGERED,
63+
},
64+
to_states={
65+
AlarmControlPanelState.ARMED_AWAY,
66+
AlarmControlPanelState.ARMED_CUSTOM_BYPASS,
67+
AlarmControlPanelState.ARMED_HOME,
68+
AlarmControlPanelState.ARMED_NIGHT,
69+
AlarmControlPanelState.ARMED_VACATION,
70+
},
71+
),
72+
"armed_away": make_entity_state_trigger_required_features(
73+
DOMAIN,
74+
AlarmControlPanelState.ARMED_AWAY,
75+
AlarmControlPanelEntityFeature.ARM_AWAY,
76+
),
77+
"armed_home": make_entity_state_trigger_required_features(
78+
DOMAIN,
79+
AlarmControlPanelState.ARMED_HOME,
80+
AlarmControlPanelEntityFeature.ARM_HOME,
81+
),
82+
"armed_night": make_entity_state_trigger_required_features(
83+
DOMAIN,
84+
AlarmControlPanelState.ARMED_NIGHT,
85+
AlarmControlPanelEntityFeature.ARM_NIGHT,
86+
),
87+
"armed_vacation": make_entity_state_trigger_required_features(
88+
DOMAIN,
89+
AlarmControlPanelState.ARMED_VACATION,
90+
AlarmControlPanelEntityFeature.ARM_VACATION,
91+
),
92+
"disarmed": make_entity_state_trigger(DOMAIN, AlarmControlPanelState.DISARMED),
93+
"triggered": make_entity_state_trigger(DOMAIN, AlarmControlPanelState.TRIGGERED),
94+
}
95+
96+
97+
async def async_get_triggers(hass: HomeAssistant) -> dict[str, type[Trigger]]:
98+
"""Return the triggers for alarm control panels."""
99+
return TRIGGERS
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
.trigger_common: &trigger_common
2+
target:
3+
entity:
4+
domain: alarm_control_panel
5+
fields: &trigger_common_fields
6+
behavior:
7+
required: true
8+
default: any
9+
selector:
10+
select:
11+
options:
12+
- first
13+
- last
14+
- any
15+
translation_key: trigger_behavior
16+
17+
armed: *trigger_common
18+
19+
armed_away:
20+
fields: *trigger_common_fields
21+
target:
22+
entity:
23+
domain: alarm_control_panel
24+
supported_features:
25+
- alarm_control_panel.AlarmControlPanelEntityFeature.ARM_AWAY
26+
27+
armed_home:
28+
fields: *trigger_common_fields
29+
target:
30+
entity:
31+
domain: alarm_control_panel
32+
supported_features:
33+
- alarm_control_panel.AlarmControlPanelEntityFeature.ARM_HOME
34+
35+
armed_night:
36+
fields: *trigger_common_fields
37+
target:
38+
entity:
39+
domain: alarm_control_panel
40+
supported_features:
41+
- alarm_control_panel.AlarmControlPanelEntityFeature.ARM_NIGHT
42+
43+
armed_vacation:
44+
fields: *trigger_common_fields
45+
target:
46+
entity:
47+
domain: alarm_control_panel
48+
supported_features:
49+
- alarm_control_panel.AlarmControlPanelEntityFeature.ARM_VACATION
50+
51+
disarmed: *trigger_common
52+
53+
triggered: *trigger_common

homeassistant/components/assist_satellite/icons.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,19 @@
1414
"start_conversation": {
1515
"service": "mdi:forum"
1616
}
17+
},
18+
"triggers": {
19+
"idle": {
20+
"trigger": "mdi:chat-sleep"
21+
},
22+
"listening": {
23+
"trigger": "mdi:chat-question"
24+
},
25+
"processing": {
26+
"trigger": "mdi:chat-processing"
27+
},
28+
"responding": {
29+
"trigger": "mdi:chat-alert"
30+
}
1731
}
1832
}

homeassistant/components/assist_satellite/strings.json

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2+
"common": {
3+
"trigger_behavior_description": "The behavior of the targeted Assist satellites to trigger on.",
4+
"trigger_behavior_name": "Behavior"
5+
},
26
"entity_component": {
37
"_": {
48
"name": "Assist satellite",
@@ -16,6 +20,13 @@
1620
"id": "Answer ID",
1721
"sentences": "Sentences"
1822
}
23+
},
24+
"trigger_behavior": {
25+
"options": {
26+
"any": "Any",
27+
"first": "First",
28+
"last": "Last"
29+
}
1930
}
2031
},
2132
"services": {
@@ -98,5 +109,51 @@
98109
"name": "Start conversation"
99110
}
100111
},
101-
"title": "Assist satellite"
112+
"title": "Assist satellite",
113+
"triggers": {
114+
"idle": {
115+
"description": "Triggers when an Assist satellite becomes idle.",
116+
"description_configured": "[%key:component::assist_satellite::triggers::idle::description%]",
117+
"fields": {
118+
"behavior": {
119+
"description": "[%key:component::assist_satellite::common::trigger_behavior_description%]",
120+
"name": "[%key:component::assist_satellite::common::trigger_behavior_name%]"
121+
}
122+
},
123+
"name": "When an Assist satellite becomes idle"
124+
},
125+
"listening": {
126+
"description": "Triggers when an Assist satellite starts listening.",
127+
"description_configured": "[%key:component::assist_satellite::triggers::listening::description%]",
128+
"fields": {
129+
"behavior": {
130+
"description": "[%key:component::assist_satellite::common::trigger_behavior_description%]",
131+
"name": "[%key:component::assist_satellite::common::trigger_behavior_name%]"
132+
}
133+
},
134+
"name": "When an Assist satellite starts listening"
135+
},
136+
"processing": {
137+
"description": "Triggers when an Assist satellite is processing.",
138+
"description_configured": "[%key:component::assist_satellite::triggers::processing::description%]",
139+
"fields": {
140+
"behavior": {
141+
"description": "[%key:component::assist_satellite::common::trigger_behavior_description%]",
142+
"name": "[%key:component::assist_satellite::common::trigger_behavior_name%]"
143+
}
144+
},
145+
"name": "When an Assist satellite is processing"
146+
},
147+
"responding": {
148+
"description": "Triggers when an Assist satellite is responding.",
149+
"description_configured": "[%key:component::assist_satellite::triggers::responding::description%]",
150+
"fields": {
151+
"behavior": {
152+
"description": "[%key:component::assist_satellite::common::trigger_behavior_description%]",
153+
"name": "[%key:component::assist_satellite::common::trigger_behavior_name%]"
154+
}
155+
},
156+
"name": "When an Assist satellite is responding"
157+
}
158+
}
102159
}

0 commit comments

Comments
 (0)