Allow templates for enabling automation triggers (#114458)
* Allow templates for enabling automation triggers * Test exception for non-limited template * Use `cv.template` instead of `cv.template_complex` * skip trigger with invalid enable template instead of returning and thus not evaluating other triggers
This commit is contained in:
parent
2a6a0e6230
commit
ba48da7678
3 changed files with 97 additions and 4 deletions
|
@ -1648,7 +1648,7 @@ TRIGGER_BASE_SCHEMA = vol.Schema(
|
||||||
vol.Required(CONF_PLATFORM): str,
|
vol.Required(CONF_PLATFORM): str,
|
||||||
vol.Optional(CONF_ID): str,
|
vol.Optional(CONF_ID): str,
|
||||||
vol.Optional(CONF_VARIABLES): SCRIPT_VARIABLES_SCHEMA,
|
vol.Optional(CONF_VARIABLES): SCRIPT_VARIABLES_SCHEMA,
|
||||||
vol.Optional(CONF_ENABLED): boolean,
|
vol.Optional(CONF_ENABLED): vol.Any(boolean, template),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,12 @@ from homeassistant.core import (
|
||||||
callback,
|
callback,
|
||||||
is_callback,
|
is_callback,
|
||||||
)
|
)
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError, TemplateError
|
||||||
from homeassistant.loader import IntegrationNotFound, async_get_integration
|
from homeassistant.loader import IntegrationNotFound, async_get_integration
|
||||||
from homeassistant.util.async_ import create_eager_task
|
from homeassistant.util.async_ import create_eager_task
|
||||||
from homeassistant.util.hass_dict import HassKey
|
from homeassistant.util.hass_dict import HassKey
|
||||||
|
|
||||||
|
from .template import Template
|
||||||
from .typing import ConfigType, TemplateVarsType
|
from .typing import ConfigType, TemplateVarsType
|
||||||
|
|
||||||
_PLATFORM_ALIASES = {
|
_PLATFORM_ALIASES = {
|
||||||
|
@ -312,7 +313,15 @@ async def async_initialize_triggers(
|
||||||
triggers: list[asyncio.Task[CALLBACK_TYPE]] = []
|
triggers: list[asyncio.Task[CALLBACK_TYPE]] = []
|
||||||
for idx, conf in enumerate(trigger_config):
|
for idx, conf in enumerate(trigger_config):
|
||||||
# Skip triggers that are not enabled
|
# Skip triggers that are not enabled
|
||||||
if not conf.get(CONF_ENABLED, True):
|
if CONF_ENABLED in conf:
|
||||||
|
enabled = conf[CONF_ENABLED]
|
||||||
|
if isinstance(enabled, Template):
|
||||||
|
try:
|
||||||
|
enabled = enabled.async_render(variables, limited=True)
|
||||||
|
except TemplateError as err:
|
||||||
|
log_cb(logging.ERROR, f"Error rendering enabled template: {err}")
|
||||||
|
continue
|
||||||
|
if not enabled:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
platform = await _async_get_trigger_platform(hass, conf)
|
platform = await _async_get_trigger_platform(hass, conf)
|
||||||
|
|
|
@ -110,6 +110,90 @@ async def test_if_disabled_trigger_not_firing(
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_trigger_enabled_templates(
|
||||||
|
hass: HomeAssistant, calls: list[ServiceCall]
|
||||||
|
) -> None:
|
||||||
|
"""Test triggers enabled by template."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"automation",
|
||||||
|
{
|
||||||
|
"automation": {
|
||||||
|
"trigger": [
|
||||||
|
{
|
||||||
|
"enabled": "{{ 'some text' }}",
|
||||||
|
"platform": "event",
|
||||||
|
"event_type": "truthy_template_trigger_event",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled": "{{ 3 == 4 }}",
|
||||||
|
"platform": "event",
|
||||||
|
"event_type": "falsy_template_trigger_event",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled": False, # eg. from a blueprints input defaulting to `false`
|
||||||
|
"platform": "event",
|
||||||
|
"event_type": "falsy_trigger_event",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"enabled": "some text", # eg. from a blueprints input value
|
||||||
|
"platform": "event",
|
||||||
|
"event_type": "truthy_trigger_event",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
hass.bus.async_fire("falsy_template_trigger_event")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert not calls
|
||||||
|
|
||||||
|
hass.bus.async_fire("falsy_trigger_event")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert not calls
|
||||||
|
|
||||||
|
hass.bus.async_fire("truthy_template_trigger_event")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
hass.bus.async_fire("truthy_trigger_event")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(calls) == 2
|
||||||
|
|
||||||
|
|
||||||
|
async def test_trigger_enabled_template_limited(
|
||||||
|
hass: HomeAssistant, calls: list[ServiceCall], caplog: pytest.LogCaptureFixture
|
||||||
|
) -> None:
|
||||||
|
"""Test triggers enabled invalid template."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"automation",
|
||||||
|
{
|
||||||
|
"automation": {
|
||||||
|
"trigger": [
|
||||||
|
{
|
||||||
|
"enabled": "{{ states('sensor.limited') }}", # only limited template supported
|
||||||
|
"platform": "event",
|
||||||
|
"event_type": "test_event",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
hass.bus.async_fire("test_event")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert not calls
|
||||||
|
assert "Error rendering enabled template" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
async def test_trigger_alias(
|
async def test_trigger_alias(
|
||||||
hass: HomeAssistant, calls: list[ServiceCall], caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, calls: list[ServiceCall], caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue