2021-03-29 16:57:51 +00:00
|
|
|
"""Trigger entity."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
import logging
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
from homeassistant.const import (
|
|
|
|
CONF_DEVICE_CLASS,
|
2021-04-02 23:57:16 +00:00
|
|
|
CONF_ICON,
|
|
|
|
CONF_NAME,
|
2021-03-29 16:57:51 +00:00
|
|
|
CONF_UNIQUE_ID,
|
|
|
|
CONF_UNIT_OF_MEASUREMENT,
|
|
|
|
)
|
|
|
|
from homeassistant.core import HomeAssistant, callback
|
|
|
|
from homeassistant.helpers import template, update_coordinator
|
|
|
|
|
|
|
|
from . import TriggerUpdateCoordinator
|
2021-04-02 23:57:16 +00:00
|
|
|
from .const import CONF_ATTRIBUTES, CONF_AVAILABILITY, CONF_PICTURE
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TriggerEntity(update_coordinator.CoordinatorEntity):
|
|
|
|
"""Template entity based on trigger data."""
|
|
|
|
|
2021-11-18 13:34:07 +00:00
|
|
|
domain: str
|
2021-03-29 16:57:51 +00:00
|
|
|
extra_template_keys: tuple | None = None
|
2021-08-25 18:21:24 +00:00
|
|
|
extra_template_keys_complex: tuple | None = None
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
hass: HomeAssistant,
|
|
|
|
coordinator: TriggerUpdateCoordinator,
|
|
|
|
config: dict,
|
2021-05-20 15:00:19 +00:00
|
|
|
) -> None:
|
2021-03-29 16:57:51 +00:00
|
|
|
"""Initialize the entity."""
|
|
|
|
super().__init__(coordinator)
|
|
|
|
|
|
|
|
entity_unique_id = config.get(CONF_UNIQUE_ID)
|
|
|
|
|
|
|
|
if entity_unique_id and coordinator.unique_id:
|
|
|
|
self._unique_id = f"{coordinator.unique_id}-{entity_unique_id}"
|
|
|
|
else:
|
|
|
|
self._unique_id = entity_unique_id
|
|
|
|
|
|
|
|
self._config = config
|
|
|
|
|
2021-04-02 23:57:16 +00:00
|
|
|
self._static_rendered = {}
|
2021-08-25 18:21:24 +00:00
|
|
|
self._to_render_simple = []
|
|
|
|
self._to_render_complex = []
|
2021-04-02 23:57:16 +00:00
|
|
|
|
|
|
|
for itm in (
|
|
|
|
CONF_NAME,
|
|
|
|
CONF_ICON,
|
|
|
|
CONF_PICTURE,
|
|
|
|
CONF_AVAILABILITY,
|
|
|
|
):
|
|
|
|
if itm not in config:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if config[itm].is_static:
|
|
|
|
self._static_rendered[itm] = config[itm].template
|
|
|
|
else:
|
2021-08-25 18:21:24 +00:00
|
|
|
self._to_render_simple.append(itm)
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
if self.extra_template_keys is not None:
|
2021-08-25 18:21:24 +00:00
|
|
|
self._to_render_simple.extend(self.extra_template_keys)
|
|
|
|
|
|
|
|
if self.extra_template_keys_complex is not None:
|
|
|
|
self._to_render_complex.extend(self.extra_template_keys_complex)
|
2021-03-29 16:57:51 +00:00
|
|
|
|
2021-04-02 23:57:16 +00:00
|
|
|
# We make a copy so our initial render is 'unknown' and not 'unavailable'
|
|
|
|
self._rendered = dict(self._static_rendered)
|
2021-09-03 07:02:45 +00:00
|
|
|
self._parse_result = {CONF_AVAILABILITY}
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Name of the entity."""
|
2021-04-02 23:57:16 +00:00
|
|
|
return self._rendered.get(CONF_NAME)
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def unique_id(self):
|
|
|
|
"""Return unique ID of the entity."""
|
|
|
|
return self._unique_id
|
|
|
|
|
|
|
|
@property
|
|
|
|
def device_class(self):
|
|
|
|
"""Return device class of the entity."""
|
|
|
|
return self._config.get(CONF_DEVICE_CLASS)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def unit_of_measurement(self) -> str | None:
|
|
|
|
"""Return unit of measurement."""
|
|
|
|
return self._config.get(CONF_UNIT_OF_MEASUREMENT)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def icon(self) -> str | None:
|
|
|
|
"""Return icon."""
|
2021-04-02 23:57:16 +00:00
|
|
|
return self._rendered.get(CONF_ICON)
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def entity_picture(self) -> str | None:
|
|
|
|
"""Return entity picture."""
|
2021-04-02 23:57:16 +00:00
|
|
|
return self._rendered.get(CONF_PICTURE)
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def available(self):
|
|
|
|
"""Return availability of the entity."""
|
|
|
|
return (
|
2021-04-02 23:57:16 +00:00
|
|
|
self._rendered is not self._static_rendered
|
2021-03-29 16:57:51 +00:00
|
|
|
and
|
|
|
|
# Check against False so `None` is ok
|
2021-04-02 23:57:16 +00:00
|
|
|
self._rendered.get(CONF_AVAILABILITY) is not False
|
2021-03-29 16:57:51 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def extra_state_attributes(self) -> dict[str, Any] | None:
|
|
|
|
"""Return extra attributes."""
|
2021-04-02 23:57:16 +00:00
|
|
|
return self._rendered.get(CONF_ATTRIBUTES)
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
async def async_added_to_hass(self) -> None:
|
|
|
|
"""Handle being added to Home Assistant."""
|
|
|
|
template.attach(self.hass, self._config)
|
|
|
|
await super().async_added_to_hass()
|
|
|
|
if self.coordinator.data is not None:
|
2021-04-22 21:54:28 +00:00
|
|
|
self._process_data()
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
@callback
|
2021-04-22 21:54:28 +00:00
|
|
|
def _process_data(self) -> None:
|
|
|
|
"""Process new data."""
|
2021-03-29 16:57:51 +00:00
|
|
|
try:
|
2021-04-02 23:57:16 +00:00
|
|
|
rendered = dict(self._static_rendered)
|
2021-03-29 16:57:51 +00:00
|
|
|
|
2021-08-25 18:21:24 +00:00
|
|
|
for key in self._to_render_simple:
|
2021-03-29 16:57:51 +00:00
|
|
|
rendered[key] = self._config[key].async_render(
|
2021-04-22 21:54:28 +00:00
|
|
|
self.coordinator.data["run_variables"],
|
|
|
|
parse_result=key in self._parse_result,
|
2021-03-29 16:57:51 +00:00
|
|
|
)
|
|
|
|
|
2021-08-25 18:21:24 +00:00
|
|
|
for key in self._to_render_complex:
|
|
|
|
rendered[key] = template.render_complex(
|
|
|
|
self._config[key],
|
|
|
|
self.coordinator.data["run_variables"],
|
|
|
|
)
|
|
|
|
|
2021-04-02 23:57:16 +00:00
|
|
|
if CONF_ATTRIBUTES in self._config:
|
|
|
|
rendered[CONF_ATTRIBUTES] = template.render_complex(
|
|
|
|
self._config[CONF_ATTRIBUTES],
|
2021-03-29 16:57:51 +00:00
|
|
|
self.coordinator.data["run_variables"],
|
|
|
|
)
|
|
|
|
|
|
|
|
self._rendered = rendered
|
|
|
|
except template.TemplateError as err:
|
|
|
|
logging.getLogger(f"{__package__}.{self.entity_id.split('.')[0]}").error(
|
|
|
|
"Error rendering %s template for %s: %s", key, self.entity_id, err
|
|
|
|
)
|
2021-04-02 23:57:16 +00:00
|
|
|
self._rendered = self._static_rendered
|
2021-03-29 16:57:51 +00:00
|
|
|
|
|
|
|
self.async_set_context(self.coordinator.data["context"])
|
2021-04-22 21:54:28 +00:00
|
|
|
|
|
|
|
@callback
|
|
|
|
def _handle_coordinator_update(self) -> None:
|
|
|
|
"""Handle updated data from the coordinator."""
|
|
|
|
self._process_data()
|
2021-03-29 16:57:51 +00:00
|
|
|
self.async_write_ha_state()
|