Do not trigger when template is true at startup (#46423)

This commit is contained in:
Anders Melchiorsen 2021-02-14 19:54:11 +01:00 committed by GitHub
parent 855bd653b4
commit f8f86fbe48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 94 additions and 6 deletions

View File

@ -37,21 +37,49 @@ async def async_attach_trigger(
template.attach(hass, time_delta)
delay_cancel = None
job = HassJob(action)
armed = False
# Arm at setup if the template is already false.
try:
if not result_as_boolean(value_template.async_render()):
armed = True
except exceptions.TemplateError as ex:
_LOGGER.warning(
"Error initializing 'template' trigger for '%s': %s",
automation_info["name"],
ex,
)
@callback
def template_listener(event, updates):
"""Listen for state changes and calls action."""
nonlocal delay_cancel
nonlocal delay_cancel, armed
result = updates.pop().result
if isinstance(result, exceptions.TemplateError):
_LOGGER.warning(
"Error evaluating 'template' trigger for '%s': %s",
automation_info["name"],
result,
)
return
if delay_cancel:
# pylint: disable=not-callable
delay_cancel()
delay_cancel = None
if not result_as_boolean(result):
armed = True
return
# Only fire when previously armed.
if not armed:
return
# Fire!
armed = False
entity_id = event and event.data.get("entity_id")
from_s = event and event.data.get("old_state")
to_s = event and event.data.get("new_state")

View File

@ -43,13 +43,15 @@ async def test_if_fires_on_change_bool(hass, calls):
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ states.test.entity.state and true }}",
"value_template": '{{ states.test.entity.state == "world" and true }}',
},
"action": {"service": "test.automation"},
}
},
)
assert len(calls) == 0
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert len(calls) == 1
@ -75,13 +77,15 @@ async def test_if_fires_on_change_str(hass, calls):
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ states.test.entity.state and "true" }}',
"value_template": '{{ states.test.entity.state == "world" and "true" }}',
},
"action": {"service": "test.automation"},
}
},
)
assert len(calls) == 0
hass.states.async_set("test.entity", "world")
await hass.async_block_till_done()
assert len(calls) == 1
@ -96,7 +100,7 @@ async def test_if_fires_on_change_str_crazy(hass, calls):
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ states.test.entity.state and "TrUE" }}',
"value_template": '{{ states.test.entity.state == "world" and "TrUE" }}',
},
"action": {"service": "test.automation"},
}
@ -108,6 +112,62 @@ async def test_if_fires_on_change_str_crazy(hass, calls):
assert len(calls) == 1
async def test_if_not_fires_when_true_at_setup(hass, calls):
"""Test for not firing during startup."""
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": '{{ states.test.entity.state == "hello" }}',
},
"action": {"service": "test.automation"},
}
},
)
assert len(calls) == 0
hass.states.async_set("test.entity", "hello", force_update=True)
await hass.async_block_till_done()
assert len(calls) == 0
async def test_if_not_fires_because_fail(hass, calls):
"""Test for not firing after TemplateError."""
hass.states.async_set("test.number", "1")
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ 84 / states.test.number.state|int == 42 }}",
},
"action": {"service": "test.automation"},
}
},
)
assert len(calls) == 0
hass.states.async_set("test.number", "2")
await hass.async_block_till_done()
assert len(calls) == 1
hass.states.async_set("test.number", "0")
await hass.async_block_till_done()
assert len(calls) == 1
hass.states.async_set("test.number", "2")
await hass.async_block_till_done()
assert len(calls) == 1
async def test_if_not_fires_on_change_bool(hass, calls):
"""Test for not firing on boolean change."""
assert await async_setup_component(
@ -117,7 +177,7 @@ async def test_if_not_fires_on_change_bool(hass, calls):
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ states.test.entity.state and false }}",
"value_template": '{{ states.test.entity.state == "world" and false }}',
},
"action": {"service": "test.automation"},
}
@ -198,7 +258,7 @@ async def test_if_fires_on_two_change(hass, calls):
automation.DOMAIN: {
"trigger": {
"platform": "template",
"value_template": "{{ states.test.entity.state and true }}",
"value_template": "{{ states.test.entity.state == 'world' }}",
},
"action": {"service": "test.automation"},
}