2019-04-03 15:40:03 +00:00
|
|
|
"""Support for covers which integrate with other components."""
|
2017-06-30 15:24:29 +00:00
|
|
|
import logging
|
|
|
|
|
|
|
|
import voluptuous as vol
|
|
|
|
|
|
|
|
from homeassistant.components.cover import (
|
2019-12-08 20:05:08 +00:00
|
|
|
ATTR_POSITION,
|
|
|
|
ATTR_TILT_POSITION,
|
|
|
|
DEVICE_CLASSES_SCHEMA,
|
2019-07-31 19:25:30 +00:00
|
|
|
ENTITY_ID_FORMAT,
|
|
|
|
PLATFORM_SCHEMA,
|
2019-12-08 20:05:08 +00:00
|
|
|
SUPPORT_CLOSE,
|
2019-07-31 19:25:30 +00:00
|
|
|
SUPPORT_CLOSE_TILT,
|
|
|
|
SUPPORT_OPEN,
|
2019-12-08 20:05:08 +00:00
|
|
|
SUPPORT_OPEN_TILT,
|
2019-07-31 19:25:30 +00:00
|
|
|
SUPPORT_SET_POSITION,
|
2019-12-08 20:05:08 +00:00
|
|
|
SUPPORT_SET_TILT_POSITION,
|
|
|
|
SUPPORT_STOP,
|
|
|
|
SUPPORT_STOP_TILT,
|
2020-04-25 16:07:15 +00:00
|
|
|
CoverEntity,
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2017-06-30 15:24:29 +00:00
|
|
|
from homeassistant.const import (
|
2019-07-31 19:25:30 +00:00
|
|
|
CONF_DEVICE_CLASS,
|
2019-12-08 20:05:08 +00:00
|
|
|
CONF_ENTITY_ID,
|
2019-07-31 19:25:30 +00:00
|
|
|
CONF_ENTITY_PICTURE_TEMPLATE,
|
2019-12-08 20:05:08 +00:00
|
|
|
CONF_FRIENDLY_NAME,
|
|
|
|
CONF_ICON_TEMPLATE,
|
2019-07-31 19:25:30 +00:00
|
|
|
CONF_OPTIMISTIC,
|
2020-08-01 22:45:55 +00:00
|
|
|
CONF_UNIQUE_ID,
|
2019-12-08 20:05:08 +00:00
|
|
|
CONF_VALUE_TEMPLATE,
|
2019-07-31 19:25:30 +00:00
|
|
|
STATE_CLOSED,
|
2019-12-08 20:05:08 +00:00
|
|
|
STATE_OPEN,
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2019-12-08 20:05:08 +00:00
|
|
|
from homeassistant.core import callback
|
2017-06-30 15:24:29 +00:00
|
|
|
from homeassistant.exceptions import TemplateError
|
|
|
|
import homeassistant.helpers.config_validation as cv
|
|
|
|
from homeassistant.helpers.entity import async_generate_entity_id
|
|
|
|
from homeassistant.helpers.script import Script
|
2019-12-08 20:05:08 +00:00
|
|
|
|
2019-09-28 11:53:16 +00:00
|
|
|
from .const import CONF_AVAILABILITY_TEMPLATE
|
2020-08-20 14:29:19 +00:00
|
|
|
from .template_entity import TemplateEntityWithAvailabilityAndImages
|
2017-06-30 15:24:29 +00:00
|
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
2019-07-31 19:25:30 +00:00
|
|
|
_VALID_STATES = [STATE_OPEN, STATE_CLOSED, "true", "false"]
|
|
|
|
|
|
|
|
CONF_COVERS = "covers"
|
|
|
|
|
|
|
|
CONF_POSITION_TEMPLATE = "position_template"
|
|
|
|
CONF_TILT_TEMPLATE = "tilt_template"
|
|
|
|
OPEN_ACTION = "open_cover"
|
|
|
|
CLOSE_ACTION = "close_cover"
|
|
|
|
STOP_ACTION = "stop_cover"
|
|
|
|
POSITION_ACTION = "set_cover_position"
|
|
|
|
TILT_ACTION = "set_cover_tilt_position"
|
|
|
|
CONF_TILT_OPTIMISTIC = "tilt_optimistic"
|
|
|
|
|
|
|
|
CONF_VALUE_OR_POSITION_TEMPLATE = "value_or_position"
|
|
|
|
CONF_OPEN_OR_CLOSE = "open_or_close"
|
|
|
|
|
|
|
|
TILT_FEATURES = (
|
|
|
|
SUPPORT_OPEN_TILT
|
|
|
|
| SUPPORT_CLOSE_TILT
|
|
|
|
| SUPPORT_STOP_TILT
|
|
|
|
| SUPPORT_SET_TILT_POSITION
|
|
|
|
)
|
|
|
|
|
2020-02-20 20:14:31 +00:00
|
|
|
COVER_SCHEMA = vol.All(
|
|
|
|
vol.Schema(
|
|
|
|
{
|
|
|
|
vol.Inclusive(OPEN_ACTION, CONF_OPEN_OR_CLOSE): cv.SCRIPT_SCHEMA,
|
|
|
|
vol.Inclusive(CLOSE_ACTION, CONF_OPEN_OR_CLOSE): cv.SCRIPT_SCHEMA,
|
|
|
|
vol.Optional(STOP_ACTION): cv.SCRIPT_SCHEMA,
|
|
|
|
vol.Exclusive(
|
|
|
|
CONF_POSITION_TEMPLATE, CONF_VALUE_OR_POSITION_TEMPLATE
|
|
|
|
): cv.template,
|
|
|
|
vol.Exclusive(
|
|
|
|
CONF_VALUE_TEMPLATE, CONF_VALUE_OR_POSITION_TEMPLATE
|
|
|
|
): cv.template,
|
|
|
|
vol.Optional(CONF_AVAILABILITY_TEMPLATE): cv.template,
|
|
|
|
vol.Optional(CONF_POSITION_TEMPLATE): cv.template,
|
|
|
|
vol.Optional(CONF_TILT_TEMPLATE): cv.template,
|
|
|
|
vol.Optional(CONF_ICON_TEMPLATE): cv.template,
|
|
|
|
vol.Optional(CONF_ENTITY_PICTURE_TEMPLATE): cv.template,
|
|
|
|
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
|
|
|
|
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
|
|
|
|
vol.Optional(CONF_TILT_OPTIMISTIC): cv.boolean,
|
|
|
|
vol.Optional(POSITION_ACTION): cv.SCRIPT_SCHEMA,
|
|
|
|
vol.Optional(TILT_ACTION): cv.SCRIPT_SCHEMA,
|
|
|
|
vol.Optional(CONF_FRIENDLY_NAME): cv.string,
|
|
|
|
vol.Optional(CONF_ENTITY_ID): cv.entity_ids,
|
2020-08-01 22:45:55 +00:00
|
|
|
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
2020-02-20 20:14:31 +00:00
|
|
|
}
|
|
|
|
),
|
|
|
|
cv.has_at_least_one_key(OPEN_ACTION, POSITION_ACTION),
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|
|
|
{vol.Required(CONF_COVERS): cv.schema_with_slug_keys(COVER_SCHEMA)}
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Set up the Template cover."""
|
|
|
|
covers = []
|
|
|
|
|
|
|
|
for device, device_config in config[CONF_COVERS].items():
|
|
|
|
state_template = device_config.get(CONF_VALUE_TEMPLATE)
|
|
|
|
position_template = device_config.get(CONF_POSITION_TEMPLATE)
|
|
|
|
tilt_template = device_config.get(CONF_TILT_TEMPLATE)
|
|
|
|
icon_template = device_config.get(CONF_ICON_TEMPLATE)
|
2019-09-28 11:53:16 +00:00
|
|
|
availability_template = device_config.get(CONF_AVAILABILITY_TEMPLATE)
|
2019-07-31 19:25:30 +00:00
|
|
|
entity_picture_template = device_config.get(CONF_ENTITY_PICTURE_TEMPLATE)
|
2019-11-26 00:30:49 +00:00
|
|
|
|
|
|
|
friendly_name = device_config.get(CONF_FRIENDLY_NAME, device)
|
2019-04-29 12:38:59 +00:00
|
|
|
device_class = device_config.get(CONF_DEVICE_CLASS)
|
2017-07-07 05:35:59 +00:00
|
|
|
open_action = device_config.get(OPEN_ACTION)
|
|
|
|
close_action = device_config.get(CLOSE_ACTION)
|
|
|
|
stop_action = device_config.get(STOP_ACTION)
|
2017-06-30 15:24:29 +00:00
|
|
|
position_action = device_config.get(POSITION_ACTION)
|
|
|
|
tilt_action = device_config.get(TILT_ACTION)
|
2017-08-25 10:33:53 +00:00
|
|
|
optimistic = device_config.get(CONF_OPTIMISTIC)
|
|
|
|
tilt_optimistic = device_config.get(CONF_TILT_OPTIMISTIC)
|
2020-08-01 22:45:55 +00:00
|
|
|
unique_id = device_config.get(CONF_UNIQUE_ID)
|
2017-06-30 15:24:29 +00:00
|
|
|
|
|
|
|
covers.append(
|
|
|
|
CoverTemplate(
|
|
|
|
hass,
|
2019-07-31 19:25:30 +00:00
|
|
|
device,
|
|
|
|
friendly_name,
|
|
|
|
device_class,
|
|
|
|
state_template,
|
|
|
|
position_template,
|
|
|
|
tilt_template,
|
|
|
|
icon_template,
|
|
|
|
entity_picture_template,
|
2019-09-28 11:53:16 +00:00
|
|
|
availability_template,
|
2019-07-31 19:25:30 +00:00
|
|
|
open_action,
|
|
|
|
close_action,
|
|
|
|
stop_action,
|
|
|
|
position_action,
|
|
|
|
tilt_action,
|
|
|
|
optimistic,
|
|
|
|
tilt_optimistic,
|
2020-08-01 22:45:55 +00:00
|
|
|
unique_id,
|
2017-06-30 15:24:29 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2018-08-24 14:37:30 +00:00
|
|
|
async_add_entities(covers)
|
2017-06-30 15:24:29 +00:00
|
|
|
|
|
|
|
|
2020-08-20 14:29:19 +00:00
|
|
|
class CoverTemplate(TemplateEntityWithAvailabilityAndImages, CoverEntity):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Representation of a Template cover."""
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
hass,
|
|
|
|
device_id,
|
|
|
|
friendly_name,
|
|
|
|
device_class,
|
|
|
|
state_template,
|
|
|
|
position_template,
|
|
|
|
tilt_template,
|
|
|
|
icon_template,
|
|
|
|
entity_picture_template,
|
2019-09-28 11:53:16 +00:00
|
|
|
availability_template,
|
2019-07-31 19:25:30 +00:00
|
|
|
open_action,
|
|
|
|
close_action,
|
|
|
|
stop_action,
|
|
|
|
position_action,
|
|
|
|
tilt_action,
|
|
|
|
optimistic,
|
|
|
|
tilt_optimistic,
|
2020-08-01 22:45:55 +00:00
|
|
|
unique_id,
|
2019-07-31 19:25:30 +00:00
|
|
|
):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Initialize the Template cover."""
|
2020-08-20 14:29:19 +00:00
|
|
|
super().__init__(
|
|
|
|
availability_template, icon_template, entity_picture_template,
|
|
|
|
)
|
2017-06-30 15:24:29 +00:00
|
|
|
self.entity_id = async_generate_entity_id(
|
2019-07-31 19:25:30 +00:00
|
|
|
ENTITY_ID_FORMAT, device_id, hass=hass
|
|
|
|
)
|
2017-06-30 15:24:29 +00:00
|
|
|
self._name = friendly_name
|
|
|
|
self._template = state_template
|
|
|
|
self._position_template = position_template
|
|
|
|
self._tilt_template = tilt_template
|
2019-04-29 12:38:59 +00:00
|
|
|
self._device_class = device_class
|
2017-07-07 05:35:59 +00:00
|
|
|
self._open_script = None
|
2020-08-12 16:39:05 +00:00
|
|
|
domain = __name__.split(".")[-2]
|
2017-07-07 05:35:59 +00:00
|
|
|
if open_action is not None:
|
2020-08-12 16:39:05 +00:00
|
|
|
self._open_script = Script(hass, open_action, friendly_name, domain)
|
2017-07-07 05:35:59 +00:00
|
|
|
self._close_script = None
|
|
|
|
if close_action is not None:
|
2020-08-12 16:39:05 +00:00
|
|
|
self._close_script = Script(hass, close_action, friendly_name, domain)
|
2017-07-07 05:35:59 +00:00
|
|
|
self._stop_script = None
|
|
|
|
if stop_action is not None:
|
2020-08-12 16:39:05 +00:00
|
|
|
self._stop_script = Script(hass, stop_action, friendly_name, domain)
|
2017-06-30 15:24:29 +00:00
|
|
|
self._position_script = None
|
|
|
|
if position_action is not None:
|
2020-08-12 16:39:05 +00:00
|
|
|
self._position_script = Script(hass, position_action, friendly_name, domain)
|
2017-06-30 15:24:29 +00:00
|
|
|
self._tilt_script = None
|
|
|
|
if tilt_action is not None:
|
2020-08-12 16:39:05 +00:00
|
|
|
self._tilt_script = Script(hass, tilt_action, friendly_name, domain)
|
2019-07-31 19:25:30 +00:00
|
|
|
self._optimistic = optimistic or (not state_template and not position_template)
|
2017-08-25 10:33:53 +00:00
|
|
|
self._tilt_optimistic = tilt_optimistic or not tilt_template
|
2017-06-30 15:24:29 +00:00
|
|
|
self._position = None
|
|
|
|
self._tilt_value = None
|
2020-08-01 22:45:55 +00:00
|
|
|
self._unique_id = unique_id
|
2017-06-30 15:24:29 +00:00
|
|
|
|
2018-06-30 16:10:59 +00:00
|
|
|
async def async_added_to_hass(self):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Register callbacks."""
|
2019-07-31 19:25:30 +00:00
|
|
|
|
2020-08-20 14:29:19 +00:00
|
|
|
if self._template:
|
|
|
|
self.add_template_attribute(
|
|
|
|
"_position", self._template, None, self._update_state
|
|
|
|
)
|
|
|
|
if self._position_template:
|
|
|
|
self.add_template_attribute(
|
|
|
|
"_position",
|
|
|
|
self._position_template,
|
|
|
|
None,
|
|
|
|
self._update_position,
|
|
|
|
none_on_template_error=True,
|
|
|
|
)
|
|
|
|
if self._tilt_template:
|
|
|
|
self.add_template_attribute(
|
|
|
|
"_tilt_value",
|
|
|
|
self._tilt_template,
|
|
|
|
None,
|
|
|
|
self._update_tilt,
|
|
|
|
none_on_template_error=True,
|
|
|
|
)
|
|
|
|
await super().async_added_to_hass()
|
|
|
|
|
|
|
|
@callback
|
|
|
|
def _update_state(self, result):
|
|
|
|
super()._update_state(result)
|
|
|
|
if isinstance(result, TemplateError):
|
|
|
|
self._position = None
|
|
|
|
return
|
|
|
|
|
|
|
|
if result in _VALID_STATES:
|
|
|
|
if result in ("true", STATE_OPEN):
|
|
|
|
self._position = 100
|
|
|
|
else:
|
|
|
|
self._position = 0
|
|
|
|
else:
|
|
|
|
_LOGGER.error(
|
|
|
|
"Received invalid cover is_on state: %s. Expected: %s",
|
|
|
|
result,
|
|
|
|
", ".join(_VALID_STATES),
|
|
|
|
)
|
|
|
|
self._position = None
|
|
|
|
|
|
|
|
@callback
|
|
|
|
def _update_position(self, result):
|
|
|
|
try:
|
|
|
|
state = float(result)
|
|
|
|
except ValueError as err:
|
|
|
|
_LOGGER.error(err)
|
|
|
|
self._position = None
|
|
|
|
return
|
|
|
|
|
|
|
|
if state < 0 or state > 100:
|
|
|
|
self._position = None
|
|
|
|
_LOGGER.error(
|
|
|
|
"Cover position value must be" " between 0 and 100." " Value was: %.2f",
|
|
|
|
state,
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self._position = state
|
|
|
|
|
|
|
|
@callback
|
|
|
|
def _update_tilt(self, result):
|
|
|
|
try:
|
|
|
|
state = float(result)
|
|
|
|
except ValueError as err:
|
|
|
|
_LOGGER.error(err)
|
|
|
|
self._tilt_value = None
|
|
|
|
return
|
|
|
|
|
|
|
|
if state < 0 or state > 100:
|
|
|
|
self._tilt_value = None
|
|
|
|
_LOGGER.error(
|
|
|
|
"Tilt value must be between 0 and 100. Value was: %.2f", state,
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self._tilt_value = state
|
2017-06-30 15:24:29 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Return the name of the cover."""
|
|
|
|
return self._name
|
|
|
|
|
2020-08-01 22:45:55 +00:00
|
|
|
@property
|
|
|
|
def unique_id(self):
|
|
|
|
"""Return the unique id of this cover."""
|
|
|
|
return self._unique_id
|
|
|
|
|
2017-06-30 15:24:29 +00:00
|
|
|
@property
|
|
|
|
def is_closed(self):
|
|
|
|
"""Return if the cover is closed."""
|
|
|
|
return self._position == 0
|
|
|
|
|
|
|
|
@property
|
|
|
|
def current_cover_position(self):
|
|
|
|
"""Return current position of cover.
|
|
|
|
|
|
|
|
None is unknown, 0 is closed, 100 is fully open.
|
|
|
|
"""
|
2018-03-23 20:54:19 +00:00
|
|
|
if self._position_template or self._position_script:
|
|
|
|
return self._position
|
|
|
|
return None
|
2017-06-30 15:24:29 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def current_cover_tilt_position(self):
|
|
|
|
"""Return current position of cover tilt.
|
|
|
|
|
|
|
|
None is unknown, 0 is closed, 100 is fully open.
|
|
|
|
"""
|
|
|
|
return self._tilt_value
|
|
|
|
|
2019-04-29 12:38:59 +00:00
|
|
|
@property
|
|
|
|
def device_class(self):
|
|
|
|
"""Return the device class of the cover."""
|
|
|
|
return self._device_class
|
|
|
|
|
2017-06-30 15:24:29 +00:00
|
|
|
@property
|
|
|
|
def supported_features(self):
|
|
|
|
"""Flag supported features."""
|
2017-07-07 05:35:59 +00:00
|
|
|
supported_features = SUPPORT_OPEN | SUPPORT_CLOSE
|
|
|
|
|
|
|
|
if self._stop_script is not None:
|
|
|
|
supported_features |= SUPPORT_STOP
|
2017-06-30 15:24:29 +00:00
|
|
|
|
2017-07-07 05:35:59 +00:00
|
|
|
if self._position_script is not None:
|
2017-06-30 15:24:29 +00:00
|
|
|
supported_features |= SUPPORT_SET_POSITION
|
|
|
|
|
2020-05-03 21:21:12 +00:00
|
|
|
if self._tilt_script is not None:
|
2017-06-30 15:24:29 +00:00
|
|
|
supported_features |= TILT_FEATURES
|
|
|
|
|
|
|
|
return supported_features
|
|
|
|
|
2018-06-30 16:10:59 +00:00
|
|
|
async def async_open_cover(self, **kwargs):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Move the cover up."""
|
2017-07-07 05:35:59 +00:00
|
|
|
if self._open_script:
|
2018-10-15 09:38:49 +00:00
|
|
|
await self._open_script.async_run(context=self._context)
|
2017-07-07 05:35:59 +00:00
|
|
|
elif self._position_script:
|
2018-10-15 09:38:49 +00:00
|
|
|
await self._position_script.async_run(
|
2019-07-31 19:25:30 +00:00
|
|
|
{"position": 100}, context=self._context
|
|
|
|
)
|
2017-08-25 10:33:53 +00:00
|
|
|
if self._optimistic:
|
|
|
|
self._position = 100
|
2020-04-01 21:19:51 +00:00
|
|
|
self.async_write_ha_state()
|
2017-06-30 15:24:29 +00:00
|
|
|
|
2018-06-30 16:10:59 +00:00
|
|
|
async def async_close_cover(self, **kwargs):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Move the cover down."""
|
2017-07-07 05:35:59 +00:00
|
|
|
if self._close_script:
|
2018-10-15 09:38:49 +00:00
|
|
|
await self._close_script.async_run(context=self._context)
|
2017-07-07 05:35:59 +00:00
|
|
|
elif self._position_script:
|
2018-10-15 09:38:49 +00:00
|
|
|
await self._position_script.async_run(
|
2019-07-31 19:25:30 +00:00
|
|
|
{"position": 0}, context=self._context
|
|
|
|
)
|
2017-08-25 10:33:53 +00:00
|
|
|
if self._optimistic:
|
|
|
|
self._position = 0
|
2020-04-01 21:19:51 +00:00
|
|
|
self.async_write_ha_state()
|
2017-06-30 15:24:29 +00:00
|
|
|
|
2018-06-30 16:10:59 +00:00
|
|
|
async def async_stop_cover(self, **kwargs):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Fire the stop action."""
|
2017-07-07 05:35:59 +00:00
|
|
|
if self._stop_script:
|
2018-10-15 09:38:49 +00:00
|
|
|
await self._stop_script.async_run(context=self._context)
|
2017-06-30 15:24:29 +00:00
|
|
|
|
2018-06-30 16:10:59 +00:00
|
|
|
async def async_set_cover_position(self, **kwargs):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Set cover position."""
|
|
|
|
self._position = kwargs[ATTR_POSITION]
|
2018-06-30 16:10:59 +00:00
|
|
|
await self._position_script.async_run(
|
2019-07-31 19:25:30 +00:00
|
|
|
{"position": self._position}, context=self._context
|
|
|
|
)
|
2017-08-25 10:33:53 +00:00
|
|
|
if self._optimistic:
|
2020-04-01 21:19:51 +00:00
|
|
|
self.async_write_ha_state()
|
2017-06-30 15:24:29 +00:00
|
|
|
|
2018-06-30 16:10:59 +00:00
|
|
|
async def async_open_cover_tilt(self, **kwargs):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Tilt the cover open."""
|
|
|
|
self._tilt_value = 100
|
2018-10-15 09:38:49 +00:00
|
|
|
await self._tilt_script.async_run(
|
2019-07-31 19:25:30 +00:00
|
|
|
{"tilt": self._tilt_value}, context=self._context
|
|
|
|
)
|
2017-08-25 10:33:53 +00:00
|
|
|
if self._tilt_optimistic:
|
2020-04-01 21:19:51 +00:00
|
|
|
self.async_write_ha_state()
|
2017-06-30 15:24:29 +00:00
|
|
|
|
2018-06-30 16:10:59 +00:00
|
|
|
async def async_close_cover_tilt(self, **kwargs):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Tilt the cover closed."""
|
|
|
|
self._tilt_value = 0
|
2018-06-30 16:10:59 +00:00
|
|
|
await self._tilt_script.async_run(
|
2019-07-31 19:25:30 +00:00
|
|
|
{"tilt": self._tilt_value}, context=self._context
|
|
|
|
)
|
2017-08-25 10:33:53 +00:00
|
|
|
if self._tilt_optimistic:
|
2020-04-01 21:19:51 +00:00
|
|
|
self.async_write_ha_state()
|
2017-06-30 15:24:29 +00:00
|
|
|
|
2018-06-30 16:10:59 +00:00
|
|
|
async def async_set_cover_tilt_position(self, **kwargs):
|
2017-06-30 15:24:29 +00:00
|
|
|
"""Move the cover tilt to a specific position."""
|
|
|
|
self._tilt_value = kwargs[ATTR_TILT_POSITION]
|
2018-10-15 09:38:49 +00:00
|
|
|
await self._tilt_script.async_run(
|
2019-07-31 19:25:30 +00:00
|
|
|
{"tilt": self._tilt_value}, context=self._context
|
|
|
|
)
|
2017-08-25 10:33:53 +00:00
|
|
|
if self._tilt_optimistic:
|
2020-04-01 21:19:51 +00:00
|
|
|
self.async_write_ha_state()
|