Add this variable for use by automation and script templates (#52774)
parent
1aec069f3a
commit
9e219d9b6e
|
@ -445,15 +445,19 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
|
||||||
trigger_context,
|
trigger_context,
|
||||||
self._trace_config,
|
self._trace_config,
|
||||||
) as automation_trace:
|
) as automation_trace:
|
||||||
|
this = None
|
||||||
|
state = self.hass.states.get(self.entity_id)
|
||||||
|
if state:
|
||||||
|
this = state.as_dict()
|
||||||
|
variables = {"this": this, **(run_variables or {})}
|
||||||
if self._variables:
|
if self._variables:
|
||||||
try:
|
try:
|
||||||
variables = self._variables.async_render(self.hass, run_variables)
|
variables = self._variables.async_render(self.hass, variables)
|
||||||
except template.TemplateError as err:
|
except template.TemplateError as err:
|
||||||
self._logger.error("Error rendering variables: %s", err)
|
self._logger.error("Error rendering variables: %s", err)
|
||||||
automation_trace.set_error(err)
|
automation_trace.set_error(err)
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
variables = run_variables
|
|
||||||
# Prepare tracing the automation
|
# Prepare tracing the automation
|
||||||
automation_trace.set_trace(trace_get())
|
automation_trace.set_trace(trace_get())
|
||||||
|
|
||||||
|
@ -569,11 +573,18 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
|
||||||
def log_cb(level, msg, **kwargs):
|
def log_cb(level, msg, **kwargs):
|
||||||
self._logger.log(level, "%s %s", msg, self.name, **kwargs)
|
self._logger.log(level, "%s %s", msg, self.name, **kwargs)
|
||||||
|
|
||||||
variables = None
|
this = None
|
||||||
|
self.async_write_ha_state()
|
||||||
|
state = self.hass.states.get(self.entity_id)
|
||||||
|
if state:
|
||||||
|
this = state.as_dict()
|
||||||
|
variables = {"this": this}
|
||||||
if self._trigger_variables:
|
if self._trigger_variables:
|
||||||
try:
|
try:
|
||||||
variables = self._trigger_variables.async_render(
|
variables = self._trigger_variables.async_render(
|
||||||
self.hass, None, limited=True
|
self.hass,
|
||||||
|
variables,
|
||||||
|
limited=True,
|
||||||
)
|
)
|
||||||
except template.TemplateError as err:
|
except template.TemplateError as err:
|
||||||
self._logger.error("Error rendering trigger variables: %s", err)
|
self._logger.error("Error rendering trigger variables: %s", err)
|
||||||
|
|
|
@ -401,7 +401,12 @@ class ScriptEntity(ToggleEntity):
|
||||||
# Prepare tracing the execution of the script's sequence
|
# Prepare tracing the execution of the script's sequence
|
||||||
script_trace.set_trace(trace_get())
|
script_trace.set_trace(trace_get())
|
||||||
with trace_path("sequence"):
|
with trace_path("sequence"):
|
||||||
return await self.script.async_run(variables, context)
|
this = None
|
||||||
|
state = self.hass.states.get(self.entity_id)
|
||||||
|
if state:
|
||||||
|
this = state.as_dict()
|
||||||
|
script_vars = {"this": this, **(variables or {})}
|
||||||
|
return await self.script.async_run(script_vars, context)
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs):
|
||||||
"""Stop running the script.
|
"""Stop running the script.
|
||||||
|
|
|
@ -1184,6 +1184,7 @@ async def test_automation_variables(hass, caplog):
|
||||||
"variables": {
|
"variables": {
|
||||||
"test_var": "defined_in_config",
|
"test_var": "defined_in_config",
|
||||||
"event_type": "{{ trigger.event.event_type }}",
|
"event_type": "{{ trigger.event.event_type }}",
|
||||||
|
"this_variables": "{{this.entity_id}}",
|
||||||
},
|
},
|
||||||
"trigger": {"platform": "event", "event_type": "test_event"},
|
"trigger": {"platform": "event", "event_type": "test_event"},
|
||||||
"action": {
|
"action": {
|
||||||
|
@ -1191,6 +1192,8 @@ async def test_automation_variables(hass, caplog):
|
||||||
"data": {
|
"data": {
|
||||||
"value": "{{ test_var }}",
|
"value": "{{ test_var }}",
|
||||||
"event_type": "{{ event_type }}",
|
"event_type": "{{ event_type }}",
|
||||||
|
"this_template": "{{this.entity_id}}",
|
||||||
|
"this_variables": "{{this_variables}}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1224,6 +1227,11 @@ async def test_automation_variables(hass, caplog):
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert calls[0].data["value"] == "defined_in_config"
|
assert calls[0].data["value"] == "defined_in_config"
|
||||||
assert calls[0].data["event_type"] == "test_event"
|
assert calls[0].data["event_type"] == "test_event"
|
||||||
|
# Verify this available to all templates
|
||||||
|
assert calls[0].data.get("this_template") == "automation.automation_0"
|
||||||
|
# Verify this available during variables rendering
|
||||||
|
assert calls[0].data.get("this_variables") == "automation.automation_0"
|
||||||
|
assert "Error rendering variables" not in caplog.text
|
||||||
|
|
||||||
hass.bus.async_fire("test_event_2")
|
hass.bus.async_fire("test_event_2")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
@ -1276,6 +1284,7 @@ async def test_automation_trigger_variables(hass, caplog):
|
||||||
},
|
},
|
||||||
"trigger_variables": {
|
"trigger_variables": {
|
||||||
"test_var": "defined_in_config",
|
"test_var": "defined_in_config",
|
||||||
|
"this_trigger_variables": "{{this.entity_id}}",
|
||||||
},
|
},
|
||||||
"trigger": {"platform": "event", "event_type": "test_event_2"},
|
"trigger": {"platform": "event", "event_type": "test_event_2"},
|
||||||
"action": {
|
"action": {
|
||||||
|
@ -1283,6 +1292,8 @@ async def test_automation_trigger_variables(hass, caplog):
|
||||||
"data": {
|
"data": {
|
||||||
"value": "{{ test_var }}",
|
"value": "{{ test_var }}",
|
||||||
"event_type": "{{ event_type }}",
|
"event_type": "{{ event_type }}",
|
||||||
|
"this_template": "{{this.entity_id}}",
|
||||||
|
"this_trigger_variables": "{{this_trigger_variables}}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1300,7 +1311,10 @@ async def test_automation_trigger_variables(hass, caplog):
|
||||||
assert len(calls) == 2
|
assert len(calls) == 2
|
||||||
assert calls[1].data["value"] == "overridden_in_config"
|
assert calls[1].data["value"] == "overridden_in_config"
|
||||||
assert calls[1].data["event_type"] == "test_event_2"
|
assert calls[1].data["event_type"] == "test_event_2"
|
||||||
|
# Verify this available to all templates
|
||||||
|
assert calls[1].data.get("this_template") == "automation.automation_1"
|
||||||
|
# Verify this available during trigger variables rendering
|
||||||
|
assert calls[1].data.get("this_trigger_variables") == "automation.automation_1"
|
||||||
assert "Error rendering variables" not in caplog.text
|
assert "Error rendering variables" not in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
@ -1332,6 +1346,35 @@ async def test_automation_bad_trigger_variables(hass, caplog):
|
||||||
assert len(calls) == 0
|
assert len(calls) == 0
|
||||||
|
|
||||||
|
|
||||||
|
async def test_automation_this_var_always(hass, caplog):
|
||||||
|
"""Test automation always has reference to this, even with no variable or trigger variables configured."""
|
||||||
|
calls = async_mock_service(hass, "test", "automation")
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
automation.DOMAIN,
|
||||||
|
{
|
||||||
|
automation.DOMAIN: [
|
||||||
|
{
|
||||||
|
"trigger": {"platform": "event", "event_type": "test_event"},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data": {
|
||||||
|
"this_template": "{{this.entity_id}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
hass.bus.async_fire("test_event")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(calls) == 1
|
||||||
|
# Verify this available to all templates
|
||||||
|
assert calls[0].data.get("this_template") == "automation.automation_0"
|
||||||
|
assert "Error rendering variables" not in caplog.text
|
||||||
|
|
||||||
|
|
||||||
async def test_blueprint_automation(hass, calls):
|
async def test_blueprint_automation(hass, calls):
|
||||||
"""Test blueprint automation."""
|
"""Test blueprint automation."""
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
|
|
|
@ -679,6 +679,7 @@ async def test_script_variables(hass, caplog):
|
||||||
"script": {
|
"script": {
|
||||||
"script1": {
|
"script1": {
|
||||||
"variables": {
|
"variables": {
|
||||||
|
"this_variable": "{{this.entity_id}}",
|
||||||
"test_var": "from_config",
|
"test_var": "from_config",
|
||||||
"templated_config_var": "{{ var_from_service | default('config-default') }}",
|
"templated_config_var": "{{ var_from_service | default('config-default') }}",
|
||||||
},
|
},
|
||||||
|
@ -688,6 +689,8 @@ async def test_script_variables(hass, caplog):
|
||||||
"data": {
|
"data": {
|
||||||
"value": "{{ test_var }}",
|
"value": "{{ test_var }}",
|
||||||
"templated_config_var": "{{ templated_config_var }}",
|
"templated_config_var": "{{ templated_config_var }}",
|
||||||
|
"this_template": "{{this.entity_id}}",
|
||||||
|
"this_variable": "{{this_variable}}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -731,6 +734,10 @@ async def test_script_variables(hass, caplog):
|
||||||
assert len(mock_calls) == 1
|
assert len(mock_calls) == 1
|
||||||
assert mock_calls[0].data["value"] == "from_config"
|
assert mock_calls[0].data["value"] == "from_config"
|
||||||
assert mock_calls[0].data["templated_config_var"] == "hello"
|
assert mock_calls[0].data["templated_config_var"] == "hello"
|
||||||
|
# Verify this available to all templates
|
||||||
|
assert mock_calls[0].data.get("this_template") == "script.script1"
|
||||||
|
# Verify this available during trigger variables rendering
|
||||||
|
assert mock_calls[0].data.get("this_variable") == "script.script1"
|
||||||
|
|
||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"script", "script1", {"test_var": "from_service"}, blocking=True
|
"script", "script1", {"test_var": "from_service"}, blocking=True
|
||||||
|
@ -758,3 +765,34 @@ async def test_script_variables(hass, caplog):
|
||||||
|
|
||||||
assert len(mock_calls) == 4
|
assert len(mock_calls) == 4
|
||||||
assert mock_calls[3].data["value"] == 1
|
assert mock_calls[3].data["value"] == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_script_this_var_always(hass, caplog):
|
||||||
|
"""Test script always has reference to this, even with no variabls are configured."""
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"script",
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"script1": {
|
||||||
|
"sequence": [
|
||||||
|
{
|
||||||
|
"service": "test.script",
|
||||||
|
"data": {
|
||||||
|
"this_template": "{{this.entity_id}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
mock_calls = async_mock_service(hass, "test", "script")
|
||||||
|
|
||||||
|
await hass.services.async_call("script", "script1", blocking=True)
|
||||||
|
|
||||||
|
assert len(mock_calls) == 1
|
||||||
|
# Verify this available to all templates
|
||||||
|
assert mock_calls[0].data.get("this_template") == "script.script1"
|
||||||
|
assert "Error rendering variables" not in caplog.text
|
||||||
|
|
Loading…
Reference in New Issue