mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 07:37:34 +00:00
Move optimistic platform logic to AbstractTemplateEntity base class (#149245)
This commit is contained in:
parent
58ddf4ea95
commit
fad5f7a47b
@ -182,7 +182,7 @@ class StateBinarySensorEntity(TemplateEntity, BinarySensorEntity, RestoreEntity)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
|
||||
self._attr_device_class = config.get(CONF_DEVICE_CLASS)
|
||||
self._template = config[CONF_STATE]
|
||||
self._template: template.Template = config[CONF_STATE]
|
||||
self._delay_cancel = None
|
||||
self._delay_on = None
|
||||
self._delay_on_raw = config.get(CONF_DELAY_ON)
|
||||
|
@ -24,7 +24,6 @@ from homeassistant.const import (
|
||||
CONF_ENTITY_ID,
|
||||
CONF_FRIENDLY_NAME,
|
||||
CONF_NAME,
|
||||
CONF_OPTIMISTIC,
|
||||
CONF_STATE,
|
||||
CONF_UNIQUE_ID,
|
||||
CONF_VALUE_TEMPLATE,
|
||||
@ -41,6 +40,7 @@ from .entity import AbstractTemplateEntity
|
||||
from .helpers import async_setup_template_platform
|
||||
from .template_entity import (
|
||||
TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY,
|
||||
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
|
||||
TemplateEntity,
|
||||
make_template_entity_common_modern_schema,
|
||||
)
|
||||
@ -97,7 +97,6 @@ COVER_YAML_SCHEMA = vol.All(
|
||||
vol.Inclusive(CLOSE_ACTION, CONF_OPEN_AND_CLOSE): cv.SCRIPT_SCHEMA,
|
||||
vol.Inclusive(OPEN_ACTION, CONF_OPEN_AND_CLOSE): cv.SCRIPT_SCHEMA,
|
||||
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
|
||||
vol.Optional(CONF_OPTIMISTIC): cv.boolean,
|
||||
vol.Optional(CONF_POSITION): cv.template,
|
||||
vol.Optional(CONF_STATE): cv.template,
|
||||
vol.Optional(CONF_TILT_OPTIMISTIC): cv.boolean,
|
||||
@ -106,7 +105,9 @@ COVER_YAML_SCHEMA = vol.All(
|
||||
vol.Optional(STOP_ACTION): cv.SCRIPT_SCHEMA,
|
||||
vol.Optional(TILT_ACTION): cv.SCRIPT_SCHEMA,
|
||||
}
|
||||
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema),
|
||||
)
|
||||
.extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
|
||||
.extend(TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA),
|
||||
cv.has_at_least_one_key(OPEN_ACTION, POSITION_ACTION),
|
||||
)
|
||||
|
||||
@ -121,7 +122,6 @@ COVER_LEGACY_YAML_SCHEMA = vol.All(
|
||||
vol.Optional(CONF_POSITION_TEMPLATE): cv.template,
|
||||
vol.Optional(CONF_TILT_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,
|
||||
@ -129,7 +129,9 @@ COVER_LEGACY_YAML_SCHEMA = vol.All(
|
||||
vol.Optional(CONF_ENTITY_ID): cv.entity_ids,
|
||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||
}
|
||||
).extend(TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY.schema),
|
||||
)
|
||||
.extend(TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY.schema)
|
||||
.extend(TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA),
|
||||
cv.has_at_least_one_key(OPEN_ACTION, POSITION_ACTION),
|
||||
)
|
||||
|
||||
@ -162,21 +164,17 @@ class AbstractTemplateCover(AbstractTemplateEntity, CoverEntity):
|
||||
"""Representation of a template cover features."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
_optimistic_entity = True
|
||||
|
||||
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
|
||||
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.
|
||||
def __init__(self, config: dict[str, Any]) -> None: # pylint: disable=super-init-not-called
|
||||
"""Initialize the features."""
|
||||
|
||||
self._template = config.get(CONF_STATE)
|
||||
self._position_template = config.get(CONF_POSITION)
|
||||
self._tilt_template = config.get(CONF_TILT)
|
||||
self._attr_device_class = config.get(CONF_DEVICE_CLASS)
|
||||
|
||||
optimistic = config.get(CONF_OPTIMISTIC)
|
||||
self._optimistic = optimistic or (
|
||||
optimistic is None and not self._template and not self._position_template
|
||||
)
|
||||
tilt_optimistic = config.get(CONF_TILT_OPTIMISTIC)
|
||||
self._tilt_optimistic = tilt_optimistic or not self._tilt_template
|
||||
self._position: int | None = None
|
||||
@ -318,7 +316,7 @@ class AbstractTemplateCover(AbstractTemplateEntity, CoverEntity):
|
||||
run_variables={"position": 100},
|
||||
context=self._context,
|
||||
)
|
||||
if self._optimistic:
|
||||
if self._attr_assumed_state:
|
||||
self._position = 100
|
||||
self.async_write_ha_state()
|
||||
|
||||
@ -332,7 +330,7 @@ class AbstractTemplateCover(AbstractTemplateEntity, CoverEntity):
|
||||
run_variables={"position": 0},
|
||||
context=self._context,
|
||||
)
|
||||
if self._optimistic:
|
||||
if self._attr_assumed_state:
|
||||
self._position = 0
|
||||
self.async_write_ha_state()
|
||||
|
||||
@ -349,7 +347,7 @@ class AbstractTemplateCover(AbstractTemplateEntity, CoverEntity):
|
||||
run_variables={"position": self._position},
|
||||
context=self._context,
|
||||
)
|
||||
if self._optimistic:
|
||||
if self._attr_assumed_state:
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_open_cover_tilt(self, **kwargs: Any) -> None:
|
||||
@ -493,10 +491,10 @@ class TriggerCoverEntity(TriggerEntity, AbstractTemplateCover):
|
||||
updater(rendered)
|
||||
write_ha_state = True
|
||||
|
||||
if not self._optimistic:
|
||||
if not self._attr_assumed_state:
|
||||
self.async_set_context(self.coordinator.data["context"])
|
||||
write_ha_state = True
|
||||
elif self._optimistic and len(self._rendered) > 0:
|
||||
elif self._attr_assumed_state and len(self._rendered) > 0:
|
||||
# In case any non optimistic template
|
||||
write_ha_state = True
|
||||
|
||||
|
@ -4,12 +4,12 @@ from abc import abstractmethod
|
||||
from collections.abc import Sequence
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.const import CONF_DEVICE_ID
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_OPTIMISTIC, CONF_STATE
|
||||
from homeassistant.core import Context, HomeAssistant, callback
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.entity import Entity, async_generate_entity_id
|
||||
from homeassistant.helpers.script import Script, _VarsType
|
||||
from homeassistant.helpers.template import TemplateStateFromEntityId
|
||||
from homeassistant.helpers.template import Template, TemplateStateFromEntityId
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import CONF_OBJECT_ID
|
||||
@ -19,13 +19,26 @@ class AbstractTemplateEntity(Entity):
|
||||
"""Actions linked to a template entity."""
|
||||
|
||||
_entity_id_format: str
|
||||
_optimistic_entity: bool = False
|
||||
_template: Template | None = None
|
||||
|
||||
def __init__(self, hass: HomeAssistant, config: ConfigType) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
) -> None:
|
||||
"""Initialize the entity."""
|
||||
|
||||
self.hass = hass
|
||||
self._action_scripts: dict[str, Script] = {}
|
||||
|
||||
if self._optimistic_entity:
|
||||
self._template = config.get(CONF_STATE)
|
||||
|
||||
self._attr_assumed_state = self._template is None or config.get(
|
||||
CONF_OPTIMISTIC, False
|
||||
)
|
||||
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
self._entity_id_format, object_id, hass=self.hass
|
||||
|
@ -15,7 +15,7 @@ from homeassistant.components.select import (
|
||||
SelectEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, CONF_STATE
|
||||
from homeassistant.const import CONF_NAME, CONF_STATE
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
@ -34,6 +34,7 @@ from .helpers import (
|
||||
)
|
||||
from .template_entity import (
|
||||
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA,
|
||||
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA,
|
||||
TemplateEntity,
|
||||
make_template_entity_common_modern_schema,
|
||||
)
|
||||
@ -45,7 +46,6 @@ CONF_OPTIONS = "options"
|
||||
CONF_SELECT_OPTION = "select_option"
|
||||
|
||||
DEFAULT_NAME = "Template Select"
|
||||
DEFAULT_OPTIMISTIC = False
|
||||
|
||||
SELECT_COMMON_SCHEMA = vol.Schema(
|
||||
{
|
||||
@ -55,15 +55,9 @@ SELECT_COMMON_SCHEMA = vol.Schema(
|
||||
}
|
||||
)
|
||||
|
||||
SELECT_YAML_SCHEMA = (
|
||||
vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
|
||||
.extend(SELECT_COMMON_SCHEMA.schema)
|
||||
)
|
||||
SELECT_YAML_SCHEMA = SELECT_COMMON_SCHEMA.extend(
|
||||
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA
|
||||
).extend(make_template_entity_common_modern_schema(DEFAULT_NAME).schema)
|
||||
|
||||
SELECT_CONFIG_ENTRY_SCHEMA = SELECT_COMMON_SCHEMA.extend(
|
||||
TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA.schema
|
||||
@ -117,24 +111,20 @@ class AbstractTemplateSelect(AbstractTemplateEntity, SelectEntity):
|
||||
"""Representation of a template select features."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
_optimistic_entity = True
|
||||
|
||||
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
|
||||
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.
|
||||
def __init__(self, config: dict[str, Any]) -> None: # pylint: disable=super-init-not-called
|
||||
"""Initialize the features."""
|
||||
self._template = config.get(CONF_STATE)
|
||||
|
||||
self._options_template = config[ATTR_OPTIONS]
|
||||
|
||||
self._attr_assumed_state = self._optimistic = (
|
||||
self._template is None or config.get(CONF_OPTIMISTIC, DEFAULT_OPTIMISTIC)
|
||||
)
|
||||
self._attr_options = []
|
||||
self._attr_current_option = None
|
||||
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Change the selected option."""
|
||||
if self._optimistic:
|
||||
if self._attr_assumed_state:
|
||||
self._attr_current_option = option
|
||||
self.async_write_ha_state()
|
||||
if select_option := self._action_scripts.get(CONF_SELECT_OPTION):
|
||||
|
@ -17,6 +17,7 @@ from homeassistant.const import (
|
||||
CONF_ICON,
|
||||
CONF_ICON_TEMPLATE,
|
||||
CONF_NAME,
|
||||
CONF_OPTIMISTIC,
|
||||
CONF_PATH,
|
||||
CONF_VARIABLES,
|
||||
STATE_UNKNOWN,
|
||||
@ -100,6 +101,11 @@ TEMPLATE_ENTITY_COMMON_CONFIG_ENTRY_SCHEMA = vol.Schema(
|
||||
).extend(TEMPLATE_ENTITY_AVAILABILITY_SCHEMA.schema)
|
||||
|
||||
|
||||
TEMPLATE_ENTITY_OPTIMISTIC_SCHEMA = {
|
||||
vol.Optional(CONF_OPTIMISTIC, default=False): cv.boolean,
|
||||
}
|
||||
|
||||
|
||||
def make_template_entity_common_modern_schema(
|
||||
default_name: str,
|
||||
) -> vol.Schema:
|
||||
|
Loading…
x
Reference in New Issue
Block a user