Support templating MQTT triggers (#45614)

* Add support for limited templates (no HASS access)

* Pass variables to automation triggers

* Support templates in MQTT triggers

* Spelling

* Handle trigger referenced by variables

* Raise on unsupported function in limited templates

* Validate MQTT trigger schema in MQTT device trigger

* Add trigger_variables to automation config schema

* Don't print stacktrace when setting up trigger throws

* Make pylint happy

* Add trigger_variables to variables

* Add debug prints, document limited template

* Add tests

* Validate MQTT trigger topic early when possible

* Improve valid_subscribe_topic_template
This commit is contained in:
Erik Montnemery 2021-02-08 10:50:38 +01:00 committed by GitHub
parent b9b1caf4d7
commit 047f16772f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 262 additions and 15 deletions

View file

@ -60,6 +60,7 @@ from .const import (
CONF_ACTION,
CONF_INITIAL_STATE,
CONF_TRIGGER,
CONF_TRIGGER_VARIABLES,
DEFAULT_INITIAL_STATE,
DOMAIN,
LOGGER,
@ -221,6 +222,7 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
action_script,
initial_state,
variables,
trigger_variables,
):
"""Initialize an automation entity."""
self._id = automation_id
@ -236,6 +238,7 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
self._referenced_devices: Optional[Set[str]] = None
self._logger = LOGGER
self._variables: ScriptVariables = variables
self._trigger_variables: ScriptVariables = trigger_variables
@property
def name(self):
@ -471,6 +474,16 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
def log_cb(level, msg, **kwargs):
self._logger.log(level, "%s %s", msg, self._name, **kwargs)
variables = None
if self._trigger_variables:
try:
variables = self._trigger_variables.async_render(
cast(HomeAssistant, self.hass), None, limited=True
)
except template.TemplateError as err:
self._logger.error("Error rendering trigger variables: %s", err)
return None
return await async_initialize_triggers(
cast(HomeAssistant, self.hass),
self._trigger_config,
@ -479,6 +492,7 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
self._name,
log_cb,
home_assistant_start,
variables,
)
@property
@ -556,6 +570,18 @@ async def _async_process_config(
else:
cond_func = None
# Add trigger variables to variables
variables = None
if CONF_TRIGGER_VARIABLES in config_block:
variables = ScriptVariables(
dict(config_block[CONF_TRIGGER_VARIABLES].as_dict())
)
if CONF_VARIABLES in config_block:
if variables:
variables.variables.update(config_block[CONF_VARIABLES].as_dict())
else:
variables = config_block[CONF_VARIABLES]
entity = AutomationEntity(
automation_id,
name,
@ -563,7 +589,8 @@ async def _async_process_config(
cond_func,
action_script,
initial_state,
config_block.get(CONF_VARIABLES),
variables,
config_block.get(CONF_TRIGGER_VARIABLES),
)
entities.append(entity)

View file

@ -21,6 +21,7 @@ from .const import (
CONF_HIDE_ENTITY,
CONF_INITIAL_STATE,
CONF_TRIGGER,
CONF_TRIGGER_VARIABLES,
DOMAIN,
)
from .helpers import async_get_blueprints
@ -43,6 +44,7 @@ PLATFORM_SCHEMA = vol.All(
vol.Required(CONF_TRIGGER): cv.TRIGGER_SCHEMA,
vol.Optional(CONF_CONDITION): _CONDITION_SCHEMA,
vol.Optional(CONF_VARIABLES): cv.SCRIPT_VARIABLES_SCHEMA,
vol.Optional(CONF_TRIGGER_VARIABLES): cv.SCRIPT_VARIABLES_SCHEMA,
vol.Required(CONF_ACTION): cv.SCRIPT_SCHEMA,
},
script.SCRIPT_MODE_SINGLE,

View file

@ -3,6 +3,7 @@ import logging
CONF_ACTION = "action"
CONF_TRIGGER = "trigger"
CONF_TRIGGER_VARIABLES = "trigger_variables"
DOMAIN = "automation"
CONF_DESCRIPTION = "description"