Allow specifying template entities based on triggers (#48169)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
Paulus Schoutsen 2021-03-29 09:57:51 -07:00 committed by GitHub
parent f815ebe9cd
commit 022f56f54d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 456 additions and 16 deletions

View file

@ -11,25 +11,24 @@ from homeassistant.components.sensor import (
)
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_FRIENDLY_NAME,
ATTR_UNIT_OF_MEASUREMENT,
CONF_DEVICE_CLASS,
CONF_ENTITY_PICTURE_TEMPLATE,
CONF_FRIENDLY_NAME,
CONF_FRIENDLY_NAME_TEMPLATE,
CONF_ICON_TEMPLATE,
CONF_SENSORS,
CONF_UNIQUE_ID,
CONF_UNIT_OF_MEASUREMENT,
CONF_VALUE_TEMPLATE,
)
from homeassistant.core import callback
from homeassistant.exceptions import TemplateError
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import async_generate_entity_id
from .const import CONF_AVAILABILITY_TEMPLATE
from .const import CONF_ATTRIBUTE_TEMPLATES, CONF_AVAILABILITY_TEMPLATE, CONF_TRIGGER
from .template_entity import TemplateEntity
CONF_ATTRIBUTE_TEMPLATES = "attribute_templates"
from .trigger_entity import TriggerEntity
SENSOR_SCHEMA = vol.All(
cv.deprecated(ATTR_ENTITY_ID),
@ -43,8 +42,8 @@ SENSOR_SCHEMA = vol.All(
vol.Optional(CONF_ATTRIBUTE_TEMPLATES, default={}): vol.Schema(
{cv.string: cv.template}
),
vol.Optional(ATTR_FRIENDLY_NAME): cv.string,
vol.Optional(ATTR_UNIT_OF_MEASUREMENT): cv.string,
vol.Optional(CONF_FRIENDLY_NAME): cv.string,
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional(CONF_UNIQUE_ID): cv.string,
@ -52,12 +51,31 @@ SENSOR_SCHEMA = vol.All(
),
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{vol.Required(CONF_SENSORS): cv.schema_with_slug_keys(SENSOR_SCHEMA)}
def trigger_warning(val):
"""Warn if a trigger is defined."""
if CONF_TRIGGER in val:
raise vol.Invalid(
"You can only add triggers to template entities if they are defined under `template:`. "
"See the template documentation for more information: https://www.home-assistant.io/integrations/template/"
)
return val
PLATFORM_SCHEMA = vol.All(
PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_TRIGGER): cv.match_all, # to raise custom warning
vol.Required(CONF_SENSORS): cv.schema_with_slug_keys(SENSOR_SCHEMA),
}
),
trigger_warning,
)
async def _async_create_entities(hass, config):
@callback
def _async_create_template_tracking_entities(hass, config):
"""Create the template sensors."""
sensors = []
@ -66,9 +84,9 @@ async def _async_create_entities(hass, config):
icon_template = device_config.get(CONF_ICON_TEMPLATE)
entity_picture_template = device_config.get(CONF_ENTITY_PICTURE_TEMPLATE)
availability_template = device_config.get(CONF_AVAILABILITY_TEMPLATE)
friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
friendly_name = device_config.get(CONF_FRIENDLY_NAME, device)
friendly_name_template = device_config.get(CONF_FRIENDLY_NAME_TEMPLATE)
unit_of_measurement = device_config.get(ATTR_UNIT_OF_MEASUREMENT)
unit_of_measurement = device_config.get(CONF_UNIT_OF_MEASUREMENT)
device_class = device_config.get(CONF_DEVICE_CLASS)
attribute_templates = device_config[CONF_ATTRIBUTE_TEMPLATES]
unique_id = device_config.get(CONF_UNIQUE_ID)
@ -95,7 +113,13 @@ async def _async_create_entities(hass, config):
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up the template sensors."""
async_add_entities(await _async_create_entities(hass, config))
if discovery_info is None:
async_add_entities(_async_create_template_tracking_entities(hass, config))
else:
async_add_entities(
TriggerSensorEntity(hass, discovery_info["coordinator"], device_id, config)
for device_id, config in discovery_info["entities"].items()
)
class SensorTemplate(TemplateEntity, SensorEntity):
@ -172,3 +196,14 @@ class SensorTemplate(TemplateEntity, SensorEntity):
def unit_of_measurement(self):
"""Return the unit_of_measurement of the device."""
return self._unit_of_measurement
class TriggerSensorEntity(TriggerEntity, SensorEntity):
"""Sensor entity based on trigger data."""
extra_template_keys = (CONF_VALUE_TEMPLATE,)
@property
def state(self) -> str | None:
"""Return state of the sensor."""
return self._rendered.get(CONF_VALUE_TEMPLATE)