1 """Provides device automations for Cover."""
3 from __future__
import annotations
5 import voluptuous
as vol
19 config_validation
as cv,
20 entity_registry
as er,
26 from .
import DOMAIN, CoverEntityFeature, CoverState
30 POSITION_CONDITION_TYPES = {
"is_position",
"is_tilt_position"}
31 STATE_CONDITION_TYPES = {
"is_open",
"is_closed",
"is_opening",
"is_closing"}
33 POSITION_CONDITION_SCHEMA = vol.All(
34 DEVICE_CONDITION_BASE_SCHEMA.extend(
36 vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
37 vol.Required(CONF_TYPE): vol.In(POSITION_CONDITION_TYPES),
38 vol.Optional(CONF_ABOVE): vol.All(
39 vol.Coerce(int), vol.Range(min=0, max=100)
41 vol.Optional(CONF_BELOW): vol.All(
42 vol.Coerce(int), vol.Range(min=0, max=100)
46 cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE),
49 STATE_CONDITION_SCHEMA = DEVICE_CONDITION_BASE_SCHEMA.extend(
51 vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
52 vol.Required(CONF_TYPE): vol.In(STATE_CONDITION_TYPES),
56 CONDITION_SCHEMA = vol.Any(POSITION_CONDITION_SCHEMA, STATE_CONDITION_SCHEMA)
60 hass: HomeAssistant, device_id: str
61 ) -> list[dict[str, str]]:
62 """List device conditions for Cover devices."""
63 registry = er.async_get(hass)
64 conditions: list[dict[str, str]] = []
67 for entry
in er.async_entries_for_device(registry, device_id):
68 if entry.domain != DOMAIN:
72 supports_open_close = supported_features & (
73 CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
78 CONF_CONDITION:
"device",
79 CONF_DEVICE_ID: device_id,
81 CONF_ENTITY_ID: entry.id,
84 if supports_open_close:
86 {**base_condition, CONF_TYPE: cond}
for cond
in STATE_CONDITION_TYPES
88 if supported_features & CoverEntityFeature.SET_POSITION:
89 conditions.append({**base_condition, CONF_TYPE:
"is_position"})
90 if supported_features & CoverEntityFeature.SET_TILT_POSITION:
91 conditions.append({**base_condition, CONF_TYPE:
"is_tilt_position"})
97 hass: HomeAssistant, config: ConfigType
98 ) -> dict[str, vol.Schema]:
99 """List condition capabilities."""
100 if config[CONF_TYPE]
not in [
"is_position",
"is_tilt_position"]:
104 "extra_fields": vol.Schema(
106 vol.Optional(CONF_ABOVE, default=0): vol.All(
107 vol.Coerce(int), vol.Range(min=0, max=100)
109 vol.Optional(CONF_BELOW, default=100): vol.All(
110 vol.Coerce(int), vol.Range(min=0, max=100)
119 hass: HomeAssistant, config: ConfigType
120 ) -> condition.ConditionCheckerType:
121 """Create a function to test a device condition."""
122 registry = er.async_get(hass)
123 entity_id = er.async_resolve_entity_id(registry, config[CONF_ENTITY_ID])
125 if config[CONF_TYPE]
in STATE_CONDITION_TYPES:
126 if config[CONF_TYPE] ==
"is_open":
127 state = CoverState.OPEN
128 elif config[CONF_TYPE] ==
"is_closed":
129 state = CoverState.CLOSED
130 elif config[CONF_TYPE] ==
"is_opening":
131 state = CoverState.OPENING
132 elif config[CONF_TYPE] ==
"is_closing":
133 state = CoverState.CLOSING
135 def test_is_state(hass: HomeAssistant, variables: TemplateVarsType) -> bool:
136 """Test if an entity is a certain state."""
137 return condition.state(hass, entity_id, state)
141 if config[CONF_TYPE] ==
"is_position":
142 position_attr =
"current_position"
143 if config[CONF_TYPE] ==
"is_tilt_position":
144 position_attr =
"current_tilt_position"
145 min_pos = config.get(CONF_ABOVE)
146 max_pos = config.get(CONF_BELOW)
149 def check_numeric_state(
150 hass: HomeAssistant, variables: TemplateVarsType =
None
152 """Return whether the criteria are met."""
153 return condition.async_numeric_state(
154 hass, entity_id, max_pos, min_pos, attribute=position_attr
157 return check_numeric_state
dict[str, vol.Schema] async_get_condition_capabilities(HomeAssistant hass, ConfigType config)
list[dict[str, str]] async_get_conditions(HomeAssistant hass, str device_id)
condition.ConditionCheckerType async_condition_from_config(HomeAssistant hass, ConfigType config)
int get_supported_features(HomeAssistant hass, str entity_id)