Home Assistant Unofficial Reference 2024.12.1
device_action.py
Go to the documentation of this file.
1 """Provides device automations for Cover."""
2 
3 from __future__ import annotations
4 
5 import voluptuous as vol
6 
7 from homeassistant.components.device_automation import async_validate_entity_schema
8 from homeassistant.const import (
9  ATTR_ENTITY_ID,
10  CONF_DEVICE_ID,
11  CONF_DOMAIN,
12  CONF_ENTITY_ID,
13  CONF_TYPE,
14  SERVICE_CLOSE_COVER,
15  SERVICE_CLOSE_COVER_TILT,
16  SERVICE_OPEN_COVER,
17  SERVICE_OPEN_COVER_TILT,
18  SERVICE_SET_COVER_POSITION,
19  SERVICE_SET_COVER_TILT_POSITION,
20  SERVICE_STOP_COVER,
21 )
22 from homeassistant.core import Context, HomeAssistant
23 from homeassistant.helpers import entity_registry as er
25 from homeassistant.helpers.entity import get_supported_features
26 from homeassistant.helpers.typing import ConfigType, TemplateVarsType
27 
28 from . import ATTR_POSITION, ATTR_TILT_POSITION, DOMAIN, CoverEntityFeature
29 
30 CMD_ACTION_TYPES = {"open", "close", "stop", "open_tilt", "close_tilt"}
31 POSITION_ACTION_TYPES = {"set_position", "set_tilt_position"}
32 
33 CMD_ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
34  {
35  vol.Required(CONF_TYPE): vol.In(CMD_ACTION_TYPES),
36  vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
37  }
38 )
39 
40 POSITION_ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
41  {
42  vol.Required(CONF_TYPE): vol.In(POSITION_ACTION_TYPES),
43  vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
44  vol.Optional("position", default=0): vol.All(
45  vol.Coerce(int), vol.Range(min=0, max=100)
46  ),
47  }
48 )
49 
50 _ACTION_SCHEMA = vol.Any(CMD_ACTION_SCHEMA, POSITION_ACTION_SCHEMA)
51 
52 
54  hass: HomeAssistant, config: ConfigType
55 ) -> ConfigType:
56  """Validate config."""
57  return async_validate_entity_schema(hass, config, _ACTION_SCHEMA)
58 
59 
61  hass: HomeAssistant, device_id: str
62 ) -> list[dict[str, str]]:
63  """List device actions for Cover devices."""
64  registry = er.async_get(hass)
65  actions = []
66 
67  # Get all the integrations entities for this device
68  for entry in er.async_entries_for_device(registry, device_id):
69  if entry.domain != DOMAIN:
70  continue
71 
72  supported_features = get_supported_features(hass, entry.entity_id)
73 
74  # Add actions for each entity that belongs to this integration
75  base_action = {
76  CONF_DEVICE_ID: device_id,
77  CONF_DOMAIN: DOMAIN,
78  CONF_ENTITY_ID: entry.id,
79  }
80 
81  if supported_features & CoverEntityFeature.SET_POSITION:
82  actions.append({**base_action, CONF_TYPE: "set_position"})
83  if supported_features & CoverEntityFeature.OPEN:
84  actions.append({**base_action, CONF_TYPE: "open"})
85  if supported_features & CoverEntityFeature.CLOSE:
86  actions.append({**base_action, CONF_TYPE: "close"})
87  if supported_features & CoverEntityFeature.STOP:
88  actions.append({**base_action, CONF_TYPE: "stop"})
89 
90  if supported_features & CoverEntityFeature.SET_TILT_POSITION:
91  actions.append({**base_action, CONF_TYPE: "set_tilt_position"})
92  if supported_features & CoverEntityFeature.OPEN_TILT:
93  actions.append({**base_action, CONF_TYPE: "open_tilt"})
94  if supported_features & CoverEntityFeature.CLOSE_TILT:
95  actions.append({**base_action, CONF_TYPE: "close_tilt"})
96 
97  return actions
98 
99 
101  hass: HomeAssistant, config: ConfigType
102 ) -> dict[str, vol.Schema]:
103  """List action capabilities."""
104  if config[CONF_TYPE] not in POSITION_ACTION_TYPES:
105  return {}
106 
107  return {
108  "extra_fields": vol.Schema(
109  {
110  vol.Optional(ATTR_POSITION, default=0): vol.All(
111  vol.Coerce(int), vol.Range(min=0, max=100)
112  )
113  }
114  )
115  }
116 
117 
119  hass: HomeAssistant,
120  config: ConfigType,
121  variables: TemplateVarsType,
122  context: Context | None,
123 ) -> None:
124  """Execute a device action."""
125  service_data = {ATTR_ENTITY_ID: config[CONF_ENTITY_ID]}
126 
127  if config[CONF_TYPE] == "open":
128  service = SERVICE_OPEN_COVER
129  elif config[CONF_TYPE] == "close":
130  service = SERVICE_CLOSE_COVER
131  elif config[CONF_TYPE] == "stop":
132  service = SERVICE_STOP_COVER
133  elif config[CONF_TYPE] == "open_tilt":
134  service = SERVICE_OPEN_COVER_TILT
135  elif config[CONF_TYPE] == "close_tilt":
136  service = SERVICE_CLOSE_COVER_TILT
137  elif config[CONF_TYPE] == "set_position":
138  service = SERVICE_SET_COVER_POSITION
139  service_data[ATTR_POSITION] = config["position"]
140  elif config[CONF_TYPE] == "set_tilt_position":
141  service = SERVICE_SET_COVER_TILT_POSITION
142  service_data[ATTR_TILT_POSITION] = config["position"]
143 
144  await hass.services.async_call(
145  DOMAIN, service, service_data, blocking=True, context=context
146  )
ConfigType async_validate_action_config(HomeAssistant hass, ConfigType config)
None async_call_action_from_config(HomeAssistant hass, ConfigType config, TemplateVarsType variables, Context|None context)
list[dict[str, str]] async_get_actions(HomeAssistant hass, str device_id)
dict[str, vol.Schema] async_get_action_capabilities(HomeAssistant hass, ConfigType config)
ConfigType async_validate_entity_schema(HomeAssistant hass, ConfigType config, VolSchemaType schema)
Definition: __init__.py:344
int get_supported_features(HomeAssistant hass, str entity_id)
Definition: entity.py:169