mirror of
https://github.com/home-assistant/core.git
synced 2026-07-07 06:46:17 +01:00
74 lines
2.8 KiB
Python
74 lines
2.8 KiB
Python
"""Provides triggers for covers."""
|
|
|
|
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
|
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN
|
|
from homeassistant.core import HomeAssistant, State, split_entity_id
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers.entity import get_device_class
|
|
from homeassistant.helpers.trigger import EntityTriggerBase
|
|
from homeassistant.helpers.typing import UNDEFINED, UndefinedType
|
|
|
|
from .const import ATTR_IS_CLOSED, DOMAIN
|
|
|
|
|
|
def get_device_class_or_undefined(
|
|
hass: HomeAssistant, entity_id: str
|
|
) -> str | None | UndefinedType:
|
|
"""Get the device class of an entity or UNDEFINED if not found."""
|
|
try:
|
|
return get_device_class(hass, entity_id)
|
|
except HomeAssistantError:
|
|
return UNDEFINED
|
|
|
|
|
|
class CoverTriggerBase(EntityTriggerBase):
|
|
"""Base trigger for cover state changes."""
|
|
|
|
_domains = {BINARY_SENSOR_DOMAIN, DOMAIN}
|
|
_binary_sensor_target_state: str
|
|
_cover_is_closed_target_value: bool
|
|
_device_classes: dict[str, str]
|
|
|
|
def entity_filter(self, entities: set[str]) -> set[str]:
|
|
"""Filter entities by cover device class."""
|
|
entities = super().entity_filter(entities)
|
|
return {
|
|
entity_id
|
|
for entity_id in entities
|
|
if get_device_class_or_undefined(self._hass, entity_id)
|
|
== self._device_classes[split_entity_id(entity_id)[0]]
|
|
}
|
|
|
|
def is_valid_state(self, state: State) -> bool:
|
|
"""Check if the state matches the target cover state."""
|
|
if split_entity_id(state.entity_id)[0] == DOMAIN:
|
|
return (
|
|
state.attributes.get(ATTR_IS_CLOSED)
|
|
== self._cover_is_closed_target_value
|
|
)
|
|
return state.state == self._binary_sensor_target_state
|
|
|
|
def is_valid_transition(self, from_state: State, to_state: State) -> bool:
|
|
"""Check if the transition is valid for a cover state change."""
|
|
if from_state.state in (STATE_UNAVAILABLE, STATE_UNKNOWN):
|
|
return False
|
|
if split_entity_id(from_state.entity_id)[0] == DOMAIN:
|
|
if (from_is_closed := from_state.attributes.get(ATTR_IS_CLOSED)) is None:
|
|
return False
|
|
return from_is_closed != to_state.attributes.get(ATTR_IS_CLOSED) # type: ignore[no-any-return]
|
|
return from_state.state != to_state.state
|
|
|
|
|
|
class CoverOpenedTriggerBase(CoverTriggerBase):
|
|
"""Base trigger for cover opened state changes."""
|
|
|
|
_binary_sensor_target_state = STATE_ON
|
|
_cover_is_closed_target_value = False
|
|
|
|
|
|
class CoverClosedTriggerBase(CoverTriggerBase):
|
|
"""Base trigger for cover closed state changes."""
|
|
|
|
_binary_sensor_target_state = STATE_OFF
|
|
_cover_is_closed_target_value = True
|