mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 14:57:09 +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)
|
template.attach(hass, time_delta)
|
||||||
delay_cancel = None
|
delay_cancel = None
|
||||||
job = HassJob(action)
|
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
|
@callback
|
||||||
def template_listener(event, updates):
|
def template_listener(event, updates):
|
||||||
"""Listen for state changes and calls action."""
|
"""Listen for state changes and calls action."""
|
||||||
nonlocal delay_cancel
|
nonlocal delay_cancel, armed
|
||||||
result = updates.pop().result
|
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:
|
if delay_cancel:
|
||||||
# pylint: disable=not-callable
|
# pylint: disable=not-callable
|
||||||
delay_cancel()
|
delay_cancel()
|
||||||
delay_cancel = None
|
delay_cancel = None
|
||||||
|
|
||||||
if not result_as_boolean(result):
|
if not result_as_boolean(result):
|
||||||
|
armed = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Only fire when previously armed.
|
||||||
|
if not armed:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Fire!
|
||||||
|
armed = False
|
||||||
|
|
||||||
entity_id = event and event.data.get("entity_id")
|
entity_id = event and event.data.get("entity_id")
|
||||||
from_s = event and event.data.get("old_state")
|
from_s = event and event.data.get("old_state")
|
||||||
to_s = event and event.data.get("new_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: {
|
automation.DOMAIN: {
|
||||||
"trigger": {
|
"trigger": {
|
||||||
"platform": "template",
|
"platform": "template",
|
||||||
"value_template": "{{ states.test.entity.state and true }}",
|
"value_template": '{{ states.test.entity.state == "world" and true }}',
|
||||||
},
|
},
|
||||||
"action": {"service": "test.automation"},
|
"action": {"service": "test.automation"},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert len(calls) == 0
|
||||||
|
|
||||||
hass.states.async_set("test.entity", "world")
|
hass.states.async_set("test.entity", "world")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
@ -75,13 +77,15 @@ async def test_if_fires_on_change_str(hass, calls):
|
|||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
"trigger": {
|
"trigger": {
|
||||||
"platform": "template",
|
"platform": "template",
|
||||||
"value_template": '{{ states.test.entity.state and "true" }}',
|
"value_template": '{{ states.test.entity.state == "world" and "true" }}',
|
||||||
},
|
},
|
||||||
"action": {"service": "test.automation"},
|
"action": {"service": "test.automation"},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert len(calls) == 0
|
||||||
|
|
||||||
hass.states.async_set("test.entity", "world")
|
hass.states.async_set("test.entity", "world")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
@ -96,7 +100,7 @@ async def test_if_fires_on_change_str_crazy(hass, calls):
|
|||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
"trigger": {
|
"trigger": {
|
||||||
"platform": "template",
|
"platform": "template",
|
||||||
"value_template": '{{ states.test.entity.state and "TrUE" }}',
|
"value_template": '{{ states.test.entity.state == "world" and "TrUE" }}',
|
||||||
},
|
},
|
||||||
"action": {"service": "test.automation"},
|
"action": {"service": "test.automation"},
|
||||||
}
|
}
|
||||||
@ -108,6 +112,62 @@ async def test_if_fires_on_change_str_crazy(hass, calls):
|
|||||||
assert len(calls) == 1
|
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):
|
async def test_if_not_fires_on_change_bool(hass, calls):
|
||||||
"""Test for not firing on boolean change."""
|
"""Test for not firing on boolean change."""
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
@ -117,7 +177,7 @@ async def test_if_not_fires_on_change_bool(hass, calls):
|
|||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
"trigger": {
|
"trigger": {
|
||||||
"platform": "template",
|
"platform": "template",
|
||||||
"value_template": "{{ states.test.entity.state and false }}",
|
"value_template": '{{ states.test.entity.state == "world" and false }}',
|
||||||
},
|
},
|
||||||
"action": {"service": "test.automation"},
|
"action": {"service": "test.automation"},
|
||||||
}
|
}
|
||||||
@ -198,7 +258,7 @@ async def test_if_fires_on_two_change(hass, calls):
|
|||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
"trigger": {
|
"trigger": {
|
||||||
"platform": "template",
|
"platform": "template",
|
||||||
"value_template": "{{ states.test.entity.state and true }}",
|
"value_template": "{{ states.test.entity.state == 'world' }}",
|
||||||
},
|
},
|
||||||
"action": {"service": "test.automation"},
|
"action": {"service": "test.automation"},
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user