mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 17:27:52 +00:00
Do not trigger when template is true at startup (#46423)
This commit is contained in:
parent
855bd653b4
commit
f8f86fbe48
@ -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")
|
||||
|
@ -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"},
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user