Simplify template integration entities (#39083)
This commit is contained in:
parent
5a9246468e
commit
796d74886e
10 changed files with 120 additions and 157 deletions
|
@ -8,7 +8,6 @@ import voluptuous as vol
|
|||
from homeassistant.core import EVENT_HOMEASSISTANT_START, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import match_all
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.event import Event, async_track_template_result
|
||||
from homeassistant.helpers.template import Template, result_as_boolean
|
||||
|
@ -24,7 +23,7 @@ class _TemplateAttribute:
|
|||
entity: Entity,
|
||||
attribute: str,
|
||||
template: Template,
|
||||
validator: Callable[[Any], Any] = match_all,
|
||||
validator: Callable[[Any], Any] = None,
|
||||
on_update: Optional[Callable[[Any], None]] = None,
|
||||
none_on_template_error: Optional[bool] = False,
|
||||
):
|
||||
|
@ -130,20 +129,82 @@ class _TemplateAttribute:
|
|||
class TemplateEntity(Entity):
|
||||
"""Entity that uses templates to calculate attributes."""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
availability_template=None,
|
||||
icon_template=None,
|
||||
entity_picture_template=None,
|
||||
attribute_templates=None,
|
||||
):
|
||||
"""Template Entity."""
|
||||
self._template_attrs = []
|
||||
self._attribute_templates = attribute_templates
|
||||
self._attributes = {}
|
||||
self._availability_template = availability_template
|
||||
self._available = True
|
||||
self._icon_template = icon_template
|
||||
self._entity_picture_template = entity_picture_template
|
||||
self._icon = None
|
||||
self._entity_picture = None
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""No polling needed."""
|
||||
return False
|
||||
|
||||
@callback
|
||||
def _update_available(self, result):
|
||||
if isinstance(result, TemplateError):
|
||||
self._available = True
|
||||
return
|
||||
|
||||
self._available = result_as_boolean(result)
|
||||
|
||||
@callback
|
||||
def _update_state(self, result):
|
||||
if self._availability_template:
|
||||
return
|
||||
|
||||
self._available = not isinstance(result, TemplateError)
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return if the device is available."""
|
||||
return self._available
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon to use in the frontend, if any."""
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def entity_picture(self):
|
||||
"""Return the entity_picture to use in the frontend, if any."""
|
||||
return self._entity_picture
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
return self._attributes
|
||||
|
||||
@callback
|
||||
def _add_attribute_template(self, attribute_key, attribute_template):
|
||||
"""Create a template tracker for the attribute."""
|
||||
|
||||
def _update_attribute(result):
|
||||
attr_result = None if isinstance(result, TemplateError) else result
|
||||
self._attributes[attribute_key] = attr_result
|
||||
|
||||
self.add_template_attribute(
|
||||
attribute_key, attribute_template, None, _update_attribute
|
||||
)
|
||||
|
||||
def add_template_attribute(
|
||||
self,
|
||||
attribute: str,
|
||||
template: Template,
|
||||
validator: Callable[[Any], Any] = match_all,
|
||||
validator: Callable[[Any], Any] = None,
|
||||
on_update: Optional[Callable[[Any], None]] = None,
|
||||
none_on_template_error: bool = False,
|
||||
) -> None:
|
||||
|
@ -183,79 +244,13 @@ class TemplateEntity(Entity):
|
|||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Run when entity about to be added to hass."""
|
||||
self.hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_START, self._async_template_startup
|
||||
)
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Call for forced update."""
|
||||
for attribute in self._template_attrs:
|
||||
if attribute.async_update:
|
||||
attribute.async_update()
|
||||
|
||||
|
||||
class TemplateEntityWithAvailability(TemplateEntity):
|
||||
"""Entity that uses templates to calculate attributes with an availability template."""
|
||||
|
||||
def __init__(self, availability_template):
|
||||
"""Template Entity."""
|
||||
self._availability_template = availability_template
|
||||
self._available = True
|
||||
super().__init__()
|
||||
|
||||
@callback
|
||||
def _update_available(self, result):
|
||||
if isinstance(result, TemplateError):
|
||||
self._available = True
|
||||
return
|
||||
|
||||
self._available = result_as_boolean(result)
|
||||
|
||||
@callback
|
||||
def _update_state(self, result):
|
||||
if self._availability_template:
|
||||
return
|
||||
|
||||
self._available = not isinstance(result, TemplateError)
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return if the device is available."""
|
||||
return self._available
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register callbacks."""
|
||||
if self._availability_template is not None:
|
||||
self.add_template_attribute(
|
||||
"_available", self._availability_template, None, self._update_available
|
||||
)
|
||||
|
||||
await super().async_added_to_hass()
|
||||
|
||||
|
||||
class TemplateEntityWithAvailabilityAndImages(TemplateEntityWithAvailability):
|
||||
"""Entity that uses templates to calculate attributes with an availability, icon, and images template."""
|
||||
|
||||
def __init__(self, availability_template, icon_template, entity_picture_template):
|
||||
"""Template Entity."""
|
||||
self._icon_template = icon_template
|
||||
self._entity_picture_template = entity_picture_template
|
||||
self._icon = None
|
||||
self._entity_picture = None
|
||||
super().__init__(availability_template)
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon to use in the frontend, if any."""
|
||||
return self._icon
|
||||
|
||||
@property
|
||||
def entity_picture(self):
|
||||
"""Return the entity_picture to use in the frontend, if any."""
|
||||
return self._entity_picture
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register callbacks."""
|
||||
if self._attribute_templates is not None:
|
||||
for key, value in self._attribute_templates.items():
|
||||
self._add_attribute_template(key, value)
|
||||
if self._icon_template is not None:
|
||||
self.add_template_attribute(
|
||||
"_icon", self._icon_template, vol.Or(cv.whitespace, cv.icon)
|
||||
|
@ -265,47 +260,12 @@ class TemplateEntityWithAvailabilityAndImages(TemplateEntityWithAvailability):
|
|||
"_entity_picture", self._entity_picture_template
|
||||
)
|
||||
|
||||
await super().async_added_to_hass()
|
||||
|
||||
|
||||
class TemplateEntityWithAttributesAvailabilityAndImages(
|
||||
TemplateEntityWithAvailabilityAndImages
|
||||
):
|
||||
"""Entity that uses templates to calculate attributes with an attributes, availability, icon, and images template."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
attribute_templates,
|
||||
availability_template,
|
||||
icon_template,
|
||||
entity_picture_template,
|
||||
):
|
||||
"""Template Entity."""
|
||||
super().__init__(availability_template, icon_template, entity_picture_template)
|
||||
self._attribute_templates = attribute_templates
|
||||
self._attributes = {}
|
||||
|
||||
@callback
|
||||
def _add_attribute_template(self, attribute_key, attribute_template):
|
||||
"""Create a template tracker for the attribute."""
|
||||
|
||||
def _update_attribute(result):
|
||||
attr_result = None if isinstance(result, TemplateError) else result
|
||||
self._attributes[attribute_key] = attr_result
|
||||
|
||||
self.add_template_attribute(
|
||||
attribute_key, attribute_template, None, _update_attribute
|
||||
self.hass.bus.async_listen_once(
|
||||
EVENT_HOMEASSISTANT_START, self._async_template_startup
|
||||
)
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
return self._attributes
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register callbacks."""
|
||||
|
||||
for key, value in self._attribute_templates.items():
|
||||
self._add_attribute_template(key, value)
|
||||
|
||||
await super().async_added_to_hass()
|
||||
async def async_update(self) -> None:
|
||||
"""Call for forced update."""
|
||||
for attribute in self._template_attrs:
|
||||
if attribute.async_update:
|
||||
attribute.async_update()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue