Home Assistant Unofficial Reference 2024.12.1
device_trigger.py
Go to the documentation of this file.
1 """Provides device automations for Climate."""
2 
3 from __future__ import annotations
4 
5 import voluptuous as vol
6 
8  DEVICE_TRIGGER_BASE_SCHEMA,
9  toggle_entity,
10 )
12  numeric_state as numeric_state_trigger,
13 )
14 from homeassistant.const import (
15  CONF_ABOVE,
16  CONF_BELOW,
17  CONF_DEVICE_ID,
18  CONF_DOMAIN,
19  CONF_ENTITY_ID,
20  CONF_FOR,
21  CONF_PLATFORM,
22  CONF_TYPE,
23  PERCENTAGE,
24 )
25 from homeassistant.core import CALLBACK_TYPE, HomeAssistant
26 from homeassistant.helpers import config_validation as cv, entity_registry as er
27 from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo
28 from homeassistant.helpers.typing import ConfigType
29 
30 from . import ATTR_CURRENT_HUMIDITY, DOMAIN
31 
32 # mypy: disallow-any-generics
33 
34 CURRENT_TRIGGER_SCHEMA = vol.All(
35  DEVICE_TRIGGER_BASE_SCHEMA.extend(
36  {
37  vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
38  vol.Required(CONF_TYPE): "current_humidity_changed",
39  vol.Optional(CONF_BELOW): vol.Any(vol.Coerce(float)),
40  vol.Optional(CONF_ABOVE): vol.Any(vol.Coerce(float)),
41  vol.Optional(CONF_FOR): cv.positive_time_period_dict,
42  }
43  ),
44  cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE),
45 )
46 
47 HUMIDIFIER_TRIGGER_SCHEMA = vol.All(
48  DEVICE_TRIGGER_BASE_SCHEMA.extend(
49  {
50  vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
51  vol.Required(CONF_TYPE): "target_humidity_changed",
52  vol.Optional(CONF_BELOW): vol.Any(vol.Coerce(int)),
53  vol.Optional(CONF_ABOVE): vol.Any(vol.Coerce(int)),
54  vol.Optional(CONF_FOR): cv.positive_time_period_dict,
55  }
56  ),
57  cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE),
58 )
59 
60 TRIGGER_SCHEMA = vol.All(
61  vol.Any(
62  CURRENT_TRIGGER_SCHEMA,
63  HUMIDIFIER_TRIGGER_SCHEMA,
64  toggle_entity.TRIGGER_SCHEMA,
65  ),
66  vol.Schema({vol.Required(CONF_DOMAIN): DOMAIN}, extra=vol.ALLOW_EXTRA),
67 )
68 
69 
71  hass: HomeAssistant, device_id: str
72 ) -> list[dict[str, str]]:
73  """List device triggers for Humidifier devices."""
74  registry = er.async_get(hass)
75  triggers = await toggle_entity.async_get_triggers(hass, device_id, DOMAIN)
76 
77  # Get all the integrations entities for this device
78  for entry in er.async_entries_for_device(registry, device_id):
79  if entry.domain != DOMAIN:
80  continue
81 
82  state = hass.states.get(entry.entity_id)
83 
84  # Add triggers for each entity that belongs to this integration
85  base_trigger = {
86  CONF_PLATFORM: "device",
87  CONF_DEVICE_ID: device_id,
88  CONF_DOMAIN: DOMAIN,
89  CONF_ENTITY_ID: entry.id,
90  }
91 
92  triggers.append(
93  {
94  **base_trigger,
95  CONF_TYPE: "target_humidity_changed",
96  }
97  )
98 
99  if state and ATTR_CURRENT_HUMIDITY in state.attributes:
100  triggers.append(
101  {
102  **base_trigger,
103  CONF_TYPE: "current_humidity_changed",
104  }
105  )
106 
107  return triggers
108 
109 
111  hass: HomeAssistant,
112  config: ConfigType,
113  action: TriggerActionType,
114  trigger_info: TriggerInfo,
115 ) -> CALLBACK_TYPE:
116  """Attach a trigger."""
117  if (trigger_type := config[CONF_TYPE]) in {
118  "current_humidity_changed",
119  "target_humidity_changed",
120  }:
121  numeric_state_config = {
122  numeric_state_trigger.CONF_PLATFORM: "numeric_state",
123  numeric_state_trigger.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
124  numeric_state_trigger.CONF_VALUE_TEMPLATE: (
125  "{{ state.attributes.humidity }}"
126  ),
127  }
128  if trigger_type == "target_humidity_changed":
129  numeric_state_config[numeric_state_trigger.CONF_VALUE_TEMPLATE] = (
130  "{{ state.attributes.humidity }}"
131  )
132  else: # trigger_type == "current_humidity_changed"
133  numeric_state_config[numeric_state_trigger.CONF_VALUE_TEMPLATE] = (
134  "{{ state.attributes.current_humidity }}"
135  )
136 
137  if CONF_ABOVE in config:
138  numeric_state_config[CONF_ABOVE] = config[CONF_ABOVE]
139  if CONF_BELOW in config:
140  numeric_state_config[CONF_BELOW] = config[CONF_BELOW]
141  if CONF_FOR in config:
142  numeric_state_config[CONF_FOR] = config[CONF_FOR]
143 
144  numeric_state_config = (
145  await numeric_state_trigger.async_validate_trigger_config(
146  hass, numeric_state_config
147  )
148  )
149  return await numeric_state_trigger.async_attach_trigger(
150  hass, numeric_state_config, action, trigger_info, platform_type="device"
151  )
152 
153  return await toggle_entity.async_attach_trigger(hass, config, action, trigger_info)
154 
155 
157  hass: HomeAssistant, config: ConfigType
158 ) -> dict[str, vol.Schema]:
159  """List trigger capabilities."""
160  if config[CONF_TYPE] in {"current_humidity_changed", "target_humidity_changed"}:
161  return {
162  "extra_fields": vol.Schema(
163  {
164  vol.Optional(
165  CONF_ABOVE, description={"suffix": PERCENTAGE}
166  ): vol.Coerce(int),
167  vol.Optional(
168  CONF_BELOW, description={"suffix": PERCENTAGE}
169  ): vol.Coerce(int),
170  vol.Optional(CONF_FOR): cv.positive_time_period_dict,
171  }
172  )
173  }
174  return await toggle_entity.async_get_trigger_capabilities(hass, config)
CALLBACK_TYPE async_attach_trigger(HomeAssistant hass, ConfigType config, TriggerActionType action, TriggerInfo trigger_info)
list[dict[str, str]] async_get_triggers(HomeAssistant hass, str device_id)
dict[str, vol.Schema] async_get_trigger_capabilities(HomeAssistant hass, ConfigType config)