mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Add initalize for abstract template entities (#147504)
This commit is contained in:
parent
b89b248b4c
commit
c058561162
@ -32,8 +32,6 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, selector, template
|
||||
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
@ -42,7 +40,7 @@ from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.helpers.script import Script
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import CONF_OBJECT_ID, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .coordinator import TriggerUpdateCoordinator
|
||||
from .entity import AbstractTemplateEntity
|
||||
from .helpers import async_setup_template_platform
|
||||
@ -213,6 +211,8 @@ class AbstractTemplateAlarmControlPanel(
|
||||
):
|
||||
"""Representation of a templated Alarm Control Panel features."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
# 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
|
||||
@ -363,12 +363,8 @@ class StateAlarmControlPanelEntity(TemplateEntity, AbstractTemplateAlarmControlP
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the panel."""
|
||||
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
AbstractTemplateAlarmControlPanel.__init__(self, config)
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, object_id, hass=hass
|
||||
)
|
||||
name = self._attr_name
|
||||
if TYPE_CHECKING:
|
||||
assert name is not None
|
||||
@ -379,11 +375,6 @@ class StateAlarmControlPanelEntity(TemplateEntity, AbstractTemplateAlarmControlP
|
||||
self.add_script(action_id, action_config, name, DOMAIN)
|
||||
self._attr_supported_features |= supported_feature
|
||||
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
hass,
|
||||
config.get(CONF_DEVICE_ID),
|
||||
)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Restore last state."""
|
||||
await super().async_added_to_hass()
|
||||
@ -434,11 +425,6 @@ class TriggerAlarmControlPanelEntity(TriggerEntity, AbstractTemplateAlarmControl
|
||||
self.add_script(action_id, action_config, name, DOMAIN)
|
||||
self._attr_supported_features |= supported_feature
|
||||
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
hass,
|
||||
config.get(CONF_DEVICE_ID),
|
||||
)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Restore last state."""
|
||||
await super().async_added_to_hass()
|
||||
|
@ -39,8 +39,6 @@ from homeassistant.const import (
|
||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, selector, template
|
||||
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
@ -51,7 +49,7 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import TriggerUpdateCoordinator
|
||||
from .const import CONF_AVAILABILITY_TEMPLATE, CONF_OBJECT_ID
|
||||
from .const import CONF_AVAILABILITY_TEMPLATE
|
||||
from .helpers import async_setup_template_platform
|
||||
from .template_entity import TEMPLATE_ENTITY_COMMON_SCHEMA, TemplateEntity
|
||||
from .trigger_entity import TriggerEntity
|
||||
@ -161,6 +159,7 @@ class StateBinarySensorEntity(TemplateEntity, BinarySensorEntity, RestoreEntity)
|
||||
"""A virtual binary sensor that triggers from another sensor."""
|
||||
|
||||
_attr_should_poll = False
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -169,11 +168,7 @@ class StateBinarySensorEntity(TemplateEntity, BinarySensorEntity, RestoreEntity)
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the Template binary sensor."""
|
||||
super().__init__(hass, config=config, unique_id=unique_id)
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, object_id, hass=hass
|
||||
)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
|
||||
self._attr_device_class = config.get(CONF_DEVICE_CLASS)
|
||||
self._template = config[CONF_STATE]
|
||||
@ -182,10 +177,6 @@ class StateBinarySensorEntity(TemplateEntity, BinarySensorEntity, RestoreEntity)
|
||||
self._delay_on_raw = config.get(CONF_DELAY_ON)
|
||||
self._delay_off = None
|
||||
self._delay_off_raw = config.get(CONF_DELAY_OFF)
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
hass,
|
||||
config.get(CONF_DEVICE_ID),
|
||||
)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Restore state."""
|
||||
@ -258,6 +249,7 @@ class StateBinarySensorEntity(TemplateEntity, BinarySensorEntity, RestoreEntity)
|
||||
class TriggerBinarySensorEntity(TriggerEntity, BinarySensorEntity, RestoreEntity):
|
||||
"""Sensor entity based on trigger data."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
domain = BINARY_SENSOR_DOMAIN
|
||||
extra_template_keys = (CONF_STATE,)
|
||||
|
||||
|
@ -3,12 +3,14 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.button import (
|
||||
DEVICE_CLASSES_SCHEMA,
|
||||
DOMAIN as BUTTON_DOMAIN,
|
||||
ENTITY_ID_FORMAT,
|
||||
ButtonEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -84,6 +86,7 @@ class StateButtonEntity(TemplateEntity, ButtonEntity):
|
||||
"""Representation of a template button."""
|
||||
|
||||
_attr_should_poll = False
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -92,8 +95,11 @@ class StateButtonEntity(TemplateEntity, ButtonEntity):
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the button."""
|
||||
super().__init__(hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
assert self._attr_name is not None
|
||||
|
||||
# Scripts can be an empty list, therefore we need to check for None
|
||||
if (action := config.get(CONF_PRESS)) is not None:
|
||||
self.add_script(CONF_PRESS, action, self._attr_name, DOMAIN)
|
||||
|
@ -32,12 +32,11 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, template
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from . import TriggerUpdateCoordinator
|
||||
from .const import CONF_OBJECT_ID, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .entity import AbstractTemplateEntity
|
||||
from .helpers import async_setup_template_platform
|
||||
from .template_entity import (
|
||||
@ -162,6 +161,8 @@ async def async_setup_platform(
|
||||
class AbstractTemplateCover(AbstractTemplateEntity, CoverEntity):
|
||||
"""Representation of a template cover features."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
# 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
|
||||
@ -397,12 +398,8 @@ class StateCoverEntity(TemplateEntity, AbstractTemplateCover):
|
||||
unique_id,
|
||||
) -> None:
|
||||
"""Initialize the Template cover."""
|
||||
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
AbstractTemplateCover.__init__(self, config)
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, object_id, hass=hass
|
||||
)
|
||||
name = self._attr_name
|
||||
if TYPE_CHECKING:
|
||||
assert name is not None
|
||||
|
@ -3,21 +3,39 @@
|
||||
from collections.abc import Sequence
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.const import CONF_DEVICE_ID
|
||||
from homeassistant.core import Context, HomeAssistant, callback
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
|
||||
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.typing import ConfigType
|
||||
|
||||
from .const import CONF_OBJECT_ID
|
||||
|
||||
|
||||
class AbstractTemplateEntity(Entity):
|
||||
"""Actions linked to a template entity."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
_entity_id_format: str
|
||||
|
||||
def __init__(self, hass: HomeAssistant, config: ConfigType) -> None:
|
||||
"""Initialize the entity."""
|
||||
|
||||
self.hass = hass
|
||||
self._action_scripts: dict[str, Script] = {}
|
||||
|
||||
if self.hass:
|
||||
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
|
||||
)
|
||||
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
self.hass,
|
||||
config.get(CONF_DEVICE_ID),
|
||||
)
|
||||
|
||||
@property
|
||||
def referenced_blueprint(self) -> str | None:
|
||||
"""Return referenced blueprint or None."""
|
||||
|
@ -34,11 +34,10 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, template
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import CONF_OBJECT_ID, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .coordinator import TriggerUpdateCoordinator
|
||||
from .entity import AbstractTemplateEntity
|
||||
from .helpers import async_setup_template_platform
|
||||
@ -154,6 +153,8 @@ async def async_setup_platform(
|
||||
class AbstractTemplateFan(AbstractTemplateEntity, FanEntity):
|
||||
"""Representation of a template fan features."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
# 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
|
||||
@ -436,12 +437,8 @@ class StateFanEntity(TemplateEntity, AbstractTemplateFan):
|
||||
unique_id,
|
||||
) -> None:
|
||||
"""Initialize the fan."""
|
||||
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
AbstractTemplateFan.__init__(self, config)
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, object_id, hass=hass
|
||||
)
|
||||
name = self._attr_name
|
||||
if TYPE_CHECKING:
|
||||
assert name is not None
|
||||
|
@ -7,7 +7,11 @@ from typing import Any
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.image import DOMAIN as IMAGE_DOMAIN, ImageEntity
|
||||
from homeassistant.components.image import (
|
||||
DOMAIN as IMAGE_DOMAIN,
|
||||
ENTITY_ID_FORMAT,
|
||||
ImageEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_NAME, CONF_URL, CONF_VERIFY_SSL
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
@ -91,6 +95,7 @@ class StateImageEntity(TemplateEntity, ImageEntity):
|
||||
|
||||
_attr_should_poll = False
|
||||
_attr_image_url: str | None = None
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -99,7 +104,7 @@ class StateImageEntity(TemplateEntity, ImageEntity):
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the image."""
|
||||
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
ImageEntity.__init__(self, hass, config[CONF_VERIFY_SSL])
|
||||
self._url_template = config[CONF_URL]
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
@ -135,6 +140,7 @@ class TriggerImageEntity(TriggerEntity, ImageEntity):
|
||||
"""Image entity based on trigger data."""
|
||||
|
||||
_attr_image_url: str | None = None
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
domain = IMAGE_DOMAIN
|
||||
extra_template_keys = (CONF_URL,)
|
||||
|
@ -43,13 +43,12 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, template
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import color as color_util
|
||||
|
||||
from . import TriggerUpdateCoordinator
|
||||
from .const import CONF_OBJECT_ID, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .entity import AbstractTemplateEntity
|
||||
from .helpers import async_setup_template_platform
|
||||
from .template_entity import (
|
||||
@ -215,6 +214,8 @@ async def async_setup_platform(
|
||||
class AbstractTemplateLight(AbstractTemplateEntity, LightEntity):
|
||||
"""Representation of a template lights features."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
# 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__( # pylint: disable=super-init-not-called
|
||||
@ -893,12 +894,8 @@ class StateLightEntity(TemplateEntity, AbstractTemplateLight):
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the light."""
|
||||
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
AbstractTemplateLight.__init__(self, config)
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, object_id, hass=hass
|
||||
)
|
||||
name = self._attr_name
|
||||
if TYPE_CHECKING:
|
||||
assert name is not None
|
||||
|
@ -9,6 +9,7 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.components.lock import (
|
||||
DOMAIN as LOCK_DOMAIN,
|
||||
ENTITY_ID_FORMAT,
|
||||
PLATFORM_SCHEMA as LOCK_PLATFORM_SCHEMA,
|
||||
LockEntity,
|
||||
LockEntityFeature,
|
||||
@ -104,6 +105,8 @@ async def async_setup_platform(
|
||||
class AbstractTemplateLock(AbstractTemplateEntity, LockEntity):
|
||||
"""Representation of a template lock features."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
# 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
|
||||
@ -283,7 +286,7 @@ class StateLockEntity(TemplateEntity, AbstractTemplateLock):
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the lock."""
|
||||
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
AbstractTemplateLock.__init__(self, config)
|
||||
name = self._attr_name
|
||||
if TYPE_CHECKING:
|
||||
|
@ -3,7 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -13,6 +13,7 @@ from homeassistant.components.number import (
|
||||
DEFAULT_MIN_VALUE,
|
||||
DEFAULT_STEP,
|
||||
DOMAIN as NUMBER_DOMAIN,
|
||||
ENTITY_ID_FORMAT,
|
||||
NumberEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -25,7 +26,6 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import config_validation as cv, selector
|
||||
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
@ -115,6 +115,7 @@ class StateNumberEntity(TemplateEntity, NumberEntity):
|
||||
"""Representation of a template number."""
|
||||
|
||||
_attr_should_poll = False
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -123,8 +124,10 @@ class StateNumberEntity(TemplateEntity, NumberEntity):
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the number."""
|
||||
super().__init__(hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
if TYPE_CHECKING:
|
||||
assert self._attr_name is not None
|
||||
|
||||
self._value_template = config[CONF_STATE]
|
||||
self.add_script(CONF_SET_VALUE, config[CONF_SET_VALUE], self._attr_name, DOMAIN)
|
||||
|
||||
@ -136,10 +139,6 @@ class StateNumberEntity(TemplateEntity, NumberEntity):
|
||||
self._attr_native_step = DEFAULT_STEP
|
||||
self._attr_native_min_value = DEFAULT_MIN_VALUE
|
||||
self._attr_native_max_value = DEFAULT_MAX_VALUE
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
hass,
|
||||
config.get(CONF_DEVICE_ID),
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_setup_templates(self) -> None:
|
||||
@ -188,6 +187,7 @@ class StateNumberEntity(TemplateEntity, NumberEntity):
|
||||
class TriggerNumberEntity(TriggerEntity, NumberEntity):
|
||||
"""Number entity based on trigger data."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
domain = NUMBER_DOMAIN
|
||||
extra_template_keys = (
|
||||
CONF_STATE,
|
||||
|
@ -11,13 +11,13 @@ from homeassistant.components.select import (
|
||||
ATTR_OPTION,
|
||||
ATTR_OPTIONS,
|
||||
DOMAIN as SELECT_DOMAIN,
|
||||
ENTITY_ID_FORMAT,
|
||||
SelectEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_NAME, CONF_OPTIMISTIC, CONF_STATE
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import config_validation as cv, selector
|
||||
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
@ -93,6 +93,8 @@ async def async_setup_entry(
|
||||
class AbstractTemplateSelect(AbstractTemplateEntity, SelectEntity):
|
||||
"""Representation of a template select features."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
# 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
|
||||
@ -132,7 +134,7 @@ class TemplateSelect(TemplateEntity, AbstractTemplateSelect):
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the select."""
|
||||
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
AbstractTemplateSelect.__init__(self, config)
|
||||
|
||||
name = self._attr_name
|
||||
@ -142,11 +144,6 @@ class TemplateSelect(TemplateEntity, AbstractTemplateSelect):
|
||||
if (select_option := config.get(CONF_SELECT_OPTION)) is not None:
|
||||
self.add_script(CONF_SELECT_OPTION, select_option, name, DOMAIN)
|
||||
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
hass,
|
||||
config.get(CONF_DEVICE_ID),
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_setup_templates(self) -> None:
|
||||
"""Set up templates."""
|
||||
|
@ -44,8 +44,6 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, selector, template
|
||||
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
@ -55,7 +53,7 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import TriggerUpdateCoordinator
|
||||
from .const import CONF_ATTRIBUTE_TEMPLATES, CONF_AVAILABILITY_TEMPLATE, CONF_OBJECT_ID
|
||||
from .const import CONF_ATTRIBUTE_TEMPLATES, CONF_AVAILABILITY_TEMPLATE
|
||||
from .helpers import async_setup_template_platform
|
||||
from .template_entity import TEMPLATE_ENTITY_COMMON_SCHEMA, TemplateEntity
|
||||
from .trigger_entity import TriggerEntity
|
||||
@ -199,6 +197,7 @@ class StateSensorEntity(TemplateEntity, SensorEntity):
|
||||
"""Representation of a Template Sensor."""
|
||||
|
||||
_attr_should_poll = False
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -207,7 +206,7 @@ class StateSensorEntity(TemplateEntity, SensorEntity):
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the sensor."""
|
||||
super().__init__(hass, config=config, fallback_name=None, unique_id=unique_id)
|
||||
super().__init__(hass, config, unique_id)
|
||||
self._attr_native_unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
|
||||
self._attr_device_class = config.get(CONF_DEVICE_CLASS)
|
||||
self._attr_state_class = config.get(CONF_STATE_CLASS)
|
||||
@ -215,14 +214,6 @@ class StateSensorEntity(TemplateEntity, SensorEntity):
|
||||
self._attr_last_reset_template: template.Template | None = config.get(
|
||||
ATTR_LAST_RESET
|
||||
)
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
hass,
|
||||
config.get(CONF_DEVICE_ID),
|
||||
)
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, object_id, hass=hass
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_setup_templates(self) -> None:
|
||||
@ -266,6 +257,7 @@ class StateSensorEntity(TemplateEntity, SensorEntity):
|
||||
class TriggerSensorEntity(TriggerEntity, RestoreSensor):
|
||||
"""Sensor entity based on trigger data."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
domain = SENSOR_DOMAIN
|
||||
extra_template_keys = (CONF_STATE,)
|
||||
|
||||
|
@ -30,8 +30,6 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, selector, template
|
||||
from homeassistant.helpers.device import async_device_info_to_link_from_device_id
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import (
|
||||
AddConfigEntryEntitiesCallback,
|
||||
AddEntitiesCallback,
|
||||
@ -40,7 +38,7 @@ from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from . import TriggerUpdateCoordinator
|
||||
from .const import CONF_OBJECT_ID, CONF_TURN_OFF, CONF_TURN_ON, DOMAIN
|
||||
from .const import CONF_TURN_OFF, CONF_TURN_ON, DOMAIN
|
||||
from .helpers import async_setup_template_platform
|
||||
from .template_entity import (
|
||||
TEMPLATE_ENTITY_COMMON_SCHEMA_LEGACY,
|
||||
@ -154,6 +152,7 @@ class StateSwitchEntity(TemplateEntity, SwitchEntity, RestoreEntity):
|
||||
"""Representation of a Template switch."""
|
||||
|
||||
_attr_should_poll = False
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -162,11 +161,8 @@ class StateSwitchEntity(TemplateEntity, SwitchEntity, RestoreEntity):
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the Template switch."""
|
||||
super().__init__(hass, config=config, unique_id=unique_id)
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, object_id, hass=hass
|
||||
)
|
||||
super().__init__(hass, config, unique_id)
|
||||
|
||||
name = self._attr_name
|
||||
if TYPE_CHECKING:
|
||||
assert name is not None
|
||||
@ -180,10 +176,6 @@ class StateSwitchEntity(TemplateEntity, SwitchEntity, RestoreEntity):
|
||||
|
||||
self._state: bool | None = False
|
||||
self._attr_assumed_state = self._template is None
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
hass,
|
||||
config.get(CONF_DEVICE_ID),
|
||||
)
|
||||
|
||||
@callback
|
||||
def _update_state(self, result):
|
||||
@ -246,6 +238,7 @@ class StateSwitchEntity(TemplateEntity, SwitchEntity, RestoreEntity):
|
||||
class TriggerSwitchEntity(TriggerEntity, SwitchEntity, RestoreEntity):
|
||||
"""Switch entity based on trigger data."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
domain = SWITCH_DOMAIN
|
||||
|
||||
def __init__(
|
||||
@ -256,6 +249,7 @@ class TriggerSwitchEntity(TriggerEntity, SwitchEntity, RestoreEntity):
|
||||
) -> None:
|
||||
"""Initialize the entity."""
|
||||
super().__init__(hass, coordinator, config)
|
||||
|
||||
name = self._rendered.get(CONF_NAME, DEFAULT_NAME)
|
||||
self._template = config.get(CONF_STATE)
|
||||
if on_action := config.get(CONF_TURN_ON):
|
||||
@ -268,11 +262,6 @@ class TriggerSwitchEntity(TriggerEntity, SwitchEntity, RestoreEntity):
|
||||
self._to_render_simple.append(CONF_STATE)
|
||||
self._parse_result.add(CONF_STATE)
|
||||
|
||||
self._attr_device_info = async_device_info_to_link_from_device_id(
|
||||
hass,
|
||||
config.get(CONF_DEVICE_ID),
|
||||
)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Restore last state."""
|
||||
await super().async_added_to_hass()
|
||||
|
@ -240,17 +240,11 @@ class TemplateEntity(AbstractTemplateEntity):
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
*,
|
||||
availability_template: Template | None = None,
|
||||
icon_template: Template | None = None,
|
||||
entity_picture_template: Template | None = None,
|
||||
attribute_templates: dict[str, Template] | None = None,
|
||||
config: ConfigType | None = None,
|
||||
fallback_name: str | None = None,
|
||||
unique_id: str | None = None,
|
||||
config: ConfigType,
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Template Entity."""
|
||||
AbstractTemplateEntity.__init__(self, hass)
|
||||
AbstractTemplateEntity.__init__(self, hass, config)
|
||||
self._template_attrs: dict[Template, list[_TemplateAttribute]] = {}
|
||||
self._template_result_info: TrackTemplateResultInfo | None = None
|
||||
self._attr_extra_state_attributes = {}
|
||||
@ -269,15 +263,6 @@ class TemplateEntity(AbstractTemplateEntity):
|
||||
| None
|
||||
) = None
|
||||
self._run_variables: ScriptVariables | dict
|
||||
if config is None:
|
||||
self._attribute_templates = attribute_templates
|
||||
self._availability_template = availability_template
|
||||
self._icon_template = icon_template
|
||||
self._entity_picture_template = entity_picture_template
|
||||
self._friendly_name_template = None
|
||||
self._run_variables = {}
|
||||
self._blueprint_inputs = None
|
||||
else:
|
||||
self._attribute_templates = config.get(CONF_ATTRIBUTES)
|
||||
self._availability_template = config.get(CONF_AVAILABILITY)
|
||||
self._icon_template = config.get(CONF_ICON)
|
||||
@ -302,7 +287,7 @@ class TemplateEntity(AbstractTemplateEntity):
|
||||
variables = {"this": DummyState()}
|
||||
|
||||
# Try to render the name as it can influence the entity ID
|
||||
self._attr_name = fallback_name
|
||||
self._attr_name = None
|
||||
if self._friendly_name_template:
|
||||
with contextlib.suppress(TemplateError):
|
||||
self._attr_name = self._friendly_name_template.async_render(
|
||||
|
@ -30,7 +30,7 @@ class TriggerEntity( # pylint: disable=hass-enforce-class-module
|
||||
"""Initialize the entity."""
|
||||
CoordinatorEntity.__init__(self, coordinator)
|
||||
TriggerBaseEntity.__init__(self, hass, config)
|
||||
AbstractTemplateEntity.__init__(self, hass)
|
||||
AbstractTemplateEntity.__init__(self, hass, config)
|
||||
|
||||
self._state_render_error = False
|
||||
|
||||
|
@ -34,11 +34,10 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, template
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import CONF_OBJECT_ID, DOMAIN
|
||||
from .const import DOMAIN
|
||||
from .coordinator import TriggerUpdateCoordinator
|
||||
from .entity import AbstractTemplateEntity
|
||||
from .helpers import async_setup_template_platform
|
||||
@ -147,6 +146,8 @@ async def async_setup_platform(
|
||||
class AbstractTemplateVacuum(AbstractTemplateEntity, StateVacuumEntity):
|
||||
"""Representation of a template vacuum features."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
# 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
|
||||
@ -302,12 +303,8 @@ class TemplateStateVacuumEntity(TemplateEntity, AbstractTemplateVacuum):
|
||||
unique_id,
|
||||
) -> None:
|
||||
"""Initialize the vacuum."""
|
||||
TemplateEntity.__init__(self, hass, config=config, unique_id=unique_id)
|
||||
TemplateEntity.__init__(self, hass, config, unique_id)
|
||||
AbstractTemplateVacuum.__init__(self, config)
|
||||
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
|
||||
self.entity_id = async_generate_entity_id(
|
||||
ENTITY_ID_FORMAT, object_id, hass=hass
|
||||
)
|
||||
name = self._attr_name
|
||||
if TYPE_CHECKING:
|
||||
assert name is not None
|
||||
|
@ -35,7 +35,6 @@ from homeassistant.const import CONF_TEMPERATURE_UNIT, STATE_UNAVAILABLE, STATE_
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import config_validation as cv, template
|
||||
from homeassistant.helpers.entity import async_generate_entity_id
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.restore_state import ExtraStoredData, RestoreEntity
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
@ -153,6 +152,7 @@ class StateWeatherEntity(TemplateEntity, WeatherEntity):
|
||||
"""Representation of a weather condition."""
|
||||
|
||||
_attr_should_poll = False
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -161,9 +161,8 @@ class StateWeatherEntity(TemplateEntity, WeatherEntity):
|
||||
unique_id: str | None,
|
||||
) -> None:
|
||||
"""Initialize the Template weather."""
|
||||
super().__init__(hass, config=config, unique_id=unique_id)
|
||||
super().__init__(hass, config, unique_id)
|
||||
|
||||
name = self._attr_name
|
||||
self._condition_template = config[CONF_CONDITION_TEMPLATE]
|
||||
self._temperature_template = config[CONF_TEMPERATURE_TEMPLATE]
|
||||
self._humidity_template = config[CONF_HUMIDITY_TEMPLATE]
|
||||
@ -191,8 +190,6 @@ class StateWeatherEntity(TemplateEntity, WeatherEntity):
|
||||
self._attr_native_visibility_unit = config.get(CONF_VISIBILITY_UNIT)
|
||||
self._attr_native_wind_speed_unit = config.get(CONF_WIND_SPEED_UNIT)
|
||||
|
||||
self.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, name, hass=hass)
|
||||
|
||||
self._condition = None
|
||||
self._temperature = None
|
||||
self._humidity = None
|
||||
@ -486,6 +483,7 @@ class WeatherExtraStoredData(ExtraStoredData):
|
||||
class TriggerWeatherEntity(TriggerEntity, WeatherEntity, RestoreEntity):
|
||||
"""Sensor entity based on trigger data."""
|
||||
|
||||
_entity_id_format = ENTITY_ID_FORMAT
|
||||
domain = WEATHER_DOMAIN
|
||||
extra_template_keys = (
|
||||
CONF_CONDITION_TEMPLATE,
|
||||
@ -501,6 +499,7 @@ class TriggerWeatherEntity(TriggerEntity, WeatherEntity, RestoreEntity):
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(hass, coordinator, config)
|
||||
|
||||
self._attr_native_precipitation_unit = config.get(CONF_PRECIPITATION_UNIT)
|
||||
self._attr_native_pressure_unit = config.get(CONF_PRESSURE_UNIT)
|
||||
self._attr_native_temperature_unit = config.get(CONF_TEMPERATURE_UNIT)
|
||||
|
@ -9,7 +9,7 @@ from homeassistant.core import HomeAssistant
|
||||
async def test_template_entity_not_implemented(hass: HomeAssistant) -> None:
|
||||
"""Test abstract template entity raises not implemented error."""
|
||||
|
||||
entity = abstract_entity.AbstractTemplateEntity(None)
|
||||
entity = abstract_entity.AbstractTemplateEntity(None, {})
|
||||
with pytest.raises(NotImplementedError):
|
||||
_ = entity.referenced_blueprint
|
||||
|
||||
|
@ -1141,7 +1141,7 @@ async def test_duplicate_templates(hass: HomeAssistant) -> None:
|
||||
"unique_id": "listening-test-event",
|
||||
"trigger": {"platform": "event", "event_type": "test_event"},
|
||||
"sensors": {
|
||||
"hello": {
|
||||
"hello_name": {
|
||||
"friendly_name": "Hello Name",
|
||||
"unique_id": "hello_name-id",
|
||||
"device_class": "battery",
|
||||
@ -1360,7 +1360,7 @@ async def test_trigger_conditional_entity_invalid_condition(
|
||||
{
|
||||
"trigger": {"platform": "event", "event_type": "test_event"},
|
||||
"sensors": {
|
||||
"hello": {
|
||||
"hello_name": {
|
||||
"friendly_name": "Hello Name",
|
||||
"value_template": "{{ trigger.event.data.beer }}",
|
||||
"entity_picture_template": "{{ '/local/dogs.png' }}",
|
||||
|
@ -9,7 +9,7 @@ from homeassistant.helpers import template
|
||||
|
||||
async def test_template_entity_requires_hass_set(hass: HomeAssistant) -> None:
|
||||
"""Test template entity requires hass to be set before accepting templates."""
|
||||
entity = template_entity.TemplateEntity(None)
|
||||
entity = template_entity.TemplateEntity(None, {}, "something_unique")
|
||||
|
||||
with pytest.raises(ValueError, match="^hass cannot be None"):
|
||||
entity.add_template_attribute("_hello", template.Template("Hello"))
|
||||
|
Loading…
x
Reference in New Issue
Block a user