Add 'wait_template' to script commands / Refactory track_template (#5827)
* Add 'wait' to script commands. * Add track_template + unittest / rename wait_template * fix lint & test * Fix handling / change automation-template / add tests * address paulus comments
This commit is contained in:
parent
5f0b2a7d15
commit
9aac2113b6
6 changed files with 326 additions and 50 deletions
|
@ -10,8 +10,7 @@ import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.const import CONF_VALUE_TEMPLATE, CONF_PLATFORM
|
from homeassistant.const import CONF_VALUE_TEMPLATE, CONF_PLATFORM
|
||||||
from homeassistant.helpers import condition
|
from homeassistant.helpers.event import async_track_template
|
||||||
from homeassistant.helpers.event import async_track_state_change
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,28 +27,16 @@ def async_trigger(hass, config, action):
|
||||||
value_template = config.get(CONF_VALUE_TEMPLATE)
|
value_template = config.get(CONF_VALUE_TEMPLATE)
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
# Local variable to keep track of if the action has already been triggered
|
|
||||||
already_triggered = False
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def state_changed_listener(entity_id, from_s, to_s):
|
def template_listener(entity_id, from_s, to_s):
|
||||||
"""Listen for state changes and calls action."""
|
"""Listen for state changes and calls action."""
|
||||||
nonlocal already_triggered
|
hass.async_run_job(action, {
|
||||||
template_result = condition.async_template(hass, value_template)
|
'trigger': {
|
||||||
|
'platform': 'template',
|
||||||
|
'entity_id': entity_id,
|
||||||
|
'from_state': from_s,
|
||||||
|
'to_state': to_s,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
# Check to see if template returns true
|
return async_track_template(hass, value_template, template_listener)
|
||||||
if template_result and not already_triggered:
|
|
||||||
already_triggered = True
|
|
||||||
hass.async_run_job(action, {
|
|
||||||
'trigger': {
|
|
||||||
'platform': 'template',
|
|
||||||
'entity_id': entity_id,
|
|
||||||
'from_state': from_s,
|
|
||||||
'to_state': to_s,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
elif not template_result:
|
|
||||||
already_triggered = False
|
|
||||||
|
|
||||||
return async_track_state_change(hass, value_template.extract_entities(),
|
|
||||||
state_changed_listener)
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ from homeassistant.loader import get_platform
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_PLATFORM, CONF_SCAN_INTERVAL, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
CONF_PLATFORM, CONF_SCAN_INTERVAL, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
||||||
CONF_ALIAS, CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, WEEKDAYS,
|
CONF_ALIAS, CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, WEEKDAYS,
|
||||||
CONF_CONDITION, CONF_BELOW, CONF_ABOVE, SUN_EVENT_SUNSET,
|
CONF_CONDITION, CONF_BELOW, CONF_ABOVE, CONF_TIMEOUT, SUN_EVENT_SUNSET,
|
||||||
SUN_EVENT_SUNRISE, CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC)
|
SUN_EVENT_SUNRISE, CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC)
|
||||||
from homeassistant.core import valid_entity_id
|
from homeassistant.core import valid_entity_id
|
||||||
from homeassistant.exceptions import TemplateError
|
from homeassistant.exceptions import TemplateError
|
||||||
|
@ -524,8 +524,14 @@ _SCRIPT_DELAY_SCHEMA = vol.Schema({
|
||||||
template)
|
template)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
_SCRIPT_WAIT_TEMPLATE_SCHEMA = vol.Schema({
|
||||||
|
vol.Optional(CONF_ALIAS): string,
|
||||||
|
vol.Required("wait_template"): template,
|
||||||
|
vol.Optional(CONF_TIMEOUT): vol.All(time_period, positive_timedelta),
|
||||||
|
})
|
||||||
|
|
||||||
SCRIPT_SCHEMA = vol.All(
|
SCRIPT_SCHEMA = vol.All(
|
||||||
ensure_list,
|
ensure_list,
|
||||||
[vol.Any(SERVICE_SCHEMA, _SCRIPT_DELAY_SCHEMA, EVENT_SCHEMA,
|
[vol.Any(SERVICE_SCHEMA, _SCRIPT_DELAY_SCHEMA,
|
||||||
CONDITION_SCHEMA)],
|
_SCRIPT_WAIT_TEMPLATE_SCHEMA, EVENT_SCHEMA, CONDITION_SCHEMA)],
|
||||||
)
|
)
|
||||||
|
|
|
@ -84,6 +84,33 @@ def async_track_state_change(hass, entity_ids, action, from_state=None,
|
||||||
track_state_change = threaded_listener_factory(async_track_state_change)
|
track_state_change = threaded_listener_factory(async_track_state_change)
|
||||||
|
|
||||||
|
|
||||||
|
def async_track_template(hass, template, action, variables=None):
|
||||||
|
"""Add a listener that track state changes with template condition."""
|
||||||
|
from . import condition
|
||||||
|
|
||||||
|
# Local variable to keep track of if the action has already been triggered
|
||||||
|
already_triggered = False
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def template_condition_listener(entity_id, from_s, to_s):
|
||||||
|
"""Check if condition is correct and run action."""
|
||||||
|
nonlocal already_triggered
|
||||||
|
template_result = condition.async_template(hass, template, variables)
|
||||||
|
|
||||||
|
# Check to see if template returns true
|
||||||
|
if template_result and not already_triggered:
|
||||||
|
already_triggered = True
|
||||||
|
hass.async_run_job(action, entity_id, from_s, to_s)
|
||||||
|
elif not template_result:
|
||||||
|
already_triggered = False
|
||||||
|
|
||||||
|
return async_track_state_change(
|
||||||
|
hass, template.extract_entities(), template_condition_listener)
|
||||||
|
|
||||||
|
|
||||||
|
track_template = threaded_listener_factory(async_track_template)
|
||||||
|
|
||||||
|
|
||||||
def async_track_point_in_time(hass, action, point_in_time):
|
def async_track_point_in_time(hass, action, point_in_time):
|
||||||
"""Add a listener that fires once after a specific point in time."""
|
"""Add a listener that fires once after a specific point in time."""
|
||||||
utc_point_in_time = dt_util.as_utc(point_in_time)
|
utc_point_in_time = dt_util.as_utc(point_in_time)
|
||||||
|
|
|
@ -6,11 +6,12 @@ from typing import Optional, Sequence
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.const import CONF_CONDITION
|
from homeassistant.const import CONF_CONDITION, CONF_TIMEOUT
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import (
|
||||||
service, condition, template, config_validation as cv)
|
service, condition, template, config_validation as cv)
|
||||||
from homeassistant.helpers.event import async_track_point_in_utc_time
|
from homeassistant.helpers.event import (
|
||||||
|
async_track_point_in_utc_time, async_track_template)
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
import homeassistant.util.dt as date_util
|
import homeassistant.util.dt as date_util
|
||||||
from homeassistant.util.async import (
|
from homeassistant.util.async import (
|
||||||
|
@ -25,6 +26,7 @@ CONF_SEQUENCE = "sequence"
|
||||||
CONF_EVENT = "event"
|
CONF_EVENT = "event"
|
||||||
CONF_EVENT_DATA = "event_data"
|
CONF_EVENT_DATA = "event_data"
|
||||||
CONF_DELAY = "delay"
|
CONF_DELAY = "delay"
|
||||||
|
CONF_WAIT_TEMPLATE = "wait_template"
|
||||||
|
|
||||||
|
|
||||||
def call_from_config(hass: HomeAssistant, config: ConfigType,
|
def call_from_config(hass: HomeAssistant, config: ConfigType,
|
||||||
|
@ -47,9 +49,9 @@ class Script():
|
||||||
self._cur = -1
|
self._cur = -1
|
||||||
self.last_action = None
|
self.last_action = None
|
||||||
self.last_triggered = None
|
self.last_triggered = None
|
||||||
self.can_cancel = any(CONF_DELAY in action for action
|
self.can_cancel = any(CONF_DELAY in action or CONF_WAIT_TEMPLATE
|
||||||
in self.sequence)
|
in action for action in self.sequence)
|
||||||
self._async_unsub_delay_listener = None
|
self._async_listener = []
|
||||||
self._template_cache = {}
|
self._template_cache = {}
|
||||||
self._config_cache = {}
|
self._config_cache = {}
|
||||||
|
|
||||||
|
@ -74,19 +76,21 @@ class Script():
|
||||||
self._log('Running script')
|
self._log('Running script')
|
||||||
self._cur = 0
|
self._cur = 0
|
||||||
|
|
||||||
# Unregister callback if we were in a delay but turn on is called
|
# Unregister callback if we were in a delay or wait but turn on is
|
||||||
# again. In that case we just continue execution.
|
# called again. In that case we just continue execution.
|
||||||
self._async_remove_listener()
|
self._async_remove_listener()
|
||||||
|
|
||||||
for cur, action in islice(enumerate(self.sequence), self._cur,
|
for cur, action in islice(enumerate(self.sequence), self._cur, None):
|
||||||
None):
|
|
||||||
|
|
||||||
if CONF_DELAY in action:
|
if CONF_DELAY in action:
|
||||||
# Call ourselves in the future to continue work
|
# Call ourselves in the future to continue work
|
||||||
@asyncio.coroutine
|
unsub = None
|
||||||
def script_delay(now):
|
|
||||||
|
@callback
|
||||||
|
def async_script_delay(now):
|
||||||
"""Called after delay is done."""
|
"""Called after delay is done."""
|
||||||
self._async_unsub_delay_listener = None
|
# pylint: disable=cell-var-from-loop
|
||||||
|
self._async_listener.remove(unsub)
|
||||||
self.hass.async_add_job(self.async_run(variables))
|
self.hass.async_add_job(self.async_run(variables))
|
||||||
|
|
||||||
delay = action[CONF_DELAY]
|
delay = action[CONF_DELAY]
|
||||||
|
@ -97,15 +101,45 @@ class Script():
|
||||||
cv.positive_timedelta)(
|
cv.positive_timedelta)(
|
||||||
delay.async_render(variables))
|
delay.async_render(variables))
|
||||||
|
|
||||||
self._async_unsub_delay_listener = \
|
unsub = async_track_point_in_utc_time(
|
||||||
async_track_point_in_utc_time(
|
self.hass, async_script_delay,
|
||||||
self.hass, script_delay,
|
date_util.utcnow() + delay
|
||||||
date_util.utcnow() + delay)
|
)
|
||||||
|
self._async_listener.append(unsub)
|
||||||
|
|
||||||
self._cur = cur + 1
|
self._cur = cur + 1
|
||||||
if self._change_listener:
|
if self._change_listener:
|
||||||
self.hass.async_add_job(self._change_listener)
|
self.hass.async_add_job(self._change_listener)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
elif CONF_WAIT_TEMPLATE in action:
|
||||||
|
# Call ourselves in the future to continue work
|
||||||
|
wait_template = action[CONF_WAIT_TEMPLATE]
|
||||||
|
wait_template.hass = self.hass
|
||||||
|
|
||||||
|
# check if condition allready okay
|
||||||
|
if condition.async_template(
|
||||||
|
self.hass, wait_template, variables):
|
||||||
|
continue
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_script_wait(entity_id, from_s, to_s):
|
||||||
|
"""Called after template condition is true."""
|
||||||
|
self._async_remove_listener()
|
||||||
|
self.hass.async_add_job(self.async_run(variables))
|
||||||
|
|
||||||
|
self._async_listener.append(async_track_template(
|
||||||
|
self.hass, wait_template, async_script_wait))
|
||||||
|
|
||||||
|
self._cur = cur + 1
|
||||||
|
if self._change_listener:
|
||||||
|
self.hass.async_add_job(self._change_listener)
|
||||||
|
|
||||||
|
if CONF_TIMEOUT in action:
|
||||||
|
self._async_set_timeout(action, variables)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
elif CONF_CONDITION in action:
|
elif CONF_CONDITION in action:
|
||||||
if not self._async_check_condition(action, variables):
|
if not self._async_check_condition(action, variables):
|
||||||
break
|
break
|
||||||
|
@ -166,11 +200,29 @@ class Script():
|
||||||
self._log("Test condition {}: {}".format(self.last_action, check))
|
self._log("Test condition {}: {}".format(self.last_action, check))
|
||||||
return check
|
return check
|
||||||
|
|
||||||
|
def _async_set_timeout(self, action, variables):
|
||||||
|
"""Schedule a timeout to abort script."""
|
||||||
|
timeout = action[CONF_TIMEOUT]
|
||||||
|
unsub = None
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_script_timeout(now):
|
||||||
|
"""Call after timeout is retrieve stop script."""
|
||||||
|
self._async_listener.remove(unsub)
|
||||||
|
self._log("Timout reach, abort script.")
|
||||||
|
self.async_stop()
|
||||||
|
|
||||||
|
unsub = async_track_point_in_utc_time(
|
||||||
|
self.hass, async_script_timeout,
|
||||||
|
date_util.utcnow() + timeout
|
||||||
|
)
|
||||||
|
self._async_listener.append(unsub)
|
||||||
|
|
||||||
def _async_remove_listener(self):
|
def _async_remove_listener(self):
|
||||||
"""Remove point in time listener, if any."""
|
"""Remove point in time listener, if any."""
|
||||||
if self._async_unsub_delay_listener:
|
for unsub in self._async_listener:
|
||||||
self._async_unsub_delay_listener()
|
unsub()
|
||||||
self._async_unsub_delay_listener = None
|
self._async_listener.clear()
|
||||||
|
|
||||||
def _log(self, msg):
|
def _log(self, msg):
|
||||||
"""Logger helper."""
|
"""Logger helper."""
|
||||||
|
|
|
@ -16,9 +16,11 @@ from homeassistant.helpers.event import (
|
||||||
track_time_change,
|
track_time_change,
|
||||||
track_state_change,
|
track_state_change,
|
||||||
track_time_interval,
|
track_time_interval,
|
||||||
|
track_template,
|
||||||
track_sunrise,
|
track_sunrise,
|
||||||
track_sunset,
|
track_sunset,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.template import Template
|
||||||
from homeassistant.components import sun
|
from homeassistant.components import sun
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
|
@ -188,6 +190,77 @@ class TestEventHelpers(unittest.TestCase):
|
||||||
self.assertEqual(5, len(wildcard_runs))
|
self.assertEqual(5, len(wildcard_runs))
|
||||||
self.assertEqual(6, len(wildercard_runs))
|
self.assertEqual(6, len(wildercard_runs))
|
||||||
|
|
||||||
|
def test_track_template(self):
|
||||||
|
"""Test tracking template."""
|
||||||
|
specific_runs = []
|
||||||
|
wildcard_runs = []
|
||||||
|
wildercard_runs = []
|
||||||
|
|
||||||
|
template_condition = Template(
|
||||||
|
"{{states.switch.test.state == 'on'}}",
|
||||||
|
self.hass
|
||||||
|
)
|
||||||
|
template_condition_var = Template(
|
||||||
|
"{{states.switch.test.state == 'on' and test == 5}}",
|
||||||
|
self.hass
|
||||||
|
)
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'off')
|
||||||
|
|
||||||
|
def specific_run_callback(entity_id, old_state, new_state):
|
||||||
|
specific_runs.append(1)
|
||||||
|
|
||||||
|
track_template(self.hass, template_condition, specific_run_callback)
|
||||||
|
|
||||||
|
@ha.callback
|
||||||
|
def wildcard_run_callback(entity_id, old_state, new_state):
|
||||||
|
wildcard_runs.append((old_state, new_state))
|
||||||
|
|
||||||
|
track_template(self.hass, template_condition, wildcard_run_callback)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def wildercard_run_callback(entity_id, old_state, new_state):
|
||||||
|
wildercard_runs.append((old_state, new_state))
|
||||||
|
|
||||||
|
track_template(
|
||||||
|
self.hass, template_condition_var, wildercard_run_callback,
|
||||||
|
{'test': 5})
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'on')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
self.assertEqual(1, len(specific_runs))
|
||||||
|
self.assertEqual(1, len(wildcard_runs))
|
||||||
|
self.assertEqual(1, len(wildercard_runs))
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'on')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
self.assertEqual(1, len(specific_runs))
|
||||||
|
self.assertEqual(1, len(wildcard_runs))
|
||||||
|
self.assertEqual(1, len(wildercard_runs))
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'off')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
self.assertEqual(1, len(specific_runs))
|
||||||
|
self.assertEqual(1, len(wildcard_runs))
|
||||||
|
self.assertEqual(1, len(wildercard_runs))
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'off')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
self.assertEqual(1, len(specific_runs))
|
||||||
|
self.assertEqual(1, len(wildcard_runs))
|
||||||
|
self.assertEqual(1, len(wildercard_runs))
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'on')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
self.assertEqual(2, len(specific_runs))
|
||||||
|
self.assertEqual(2, len(wildcard_runs))
|
||||||
|
self.assertEqual(2, len(wildercard_runs))
|
||||||
|
|
||||||
def test_track_time_interval(self):
|
def test_track_time_interval(self):
|
||||||
"""Test tracking time interval."""
|
"""Test tracking time interval."""
|
||||||
specific_runs = []
|
specific_runs = []
|
||||||
|
|
|
@ -131,7 +131,6 @@ class TestScriptHelper(unittest.TestCase):
|
||||||
{'event': event}]))
|
{'event': event}]))
|
||||||
|
|
||||||
script_obj.run()
|
script_obj.run()
|
||||||
|
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert script_obj.is_running
|
assert script_obj.is_running
|
||||||
|
@ -164,7 +163,6 @@ class TestScriptHelper(unittest.TestCase):
|
||||||
{'event': event}]))
|
{'event': event}]))
|
||||||
|
|
||||||
script_obj.run()
|
script_obj.run()
|
||||||
|
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert script_obj.is_running
|
assert script_obj.is_running
|
||||||
|
@ -196,7 +194,6 @@ class TestScriptHelper(unittest.TestCase):
|
||||||
{'event': event}]))
|
{'event': event}]))
|
||||||
|
|
||||||
script_obj.run()
|
script_obj.run()
|
||||||
|
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
|
|
||||||
assert script_obj.is_running
|
assert script_obj.is_running
|
||||||
|
@ -214,6 +211,140 @@ class TestScriptHelper(unittest.TestCase):
|
||||||
assert not script_obj.is_running
|
assert not script_obj.is_running
|
||||||
assert len(events) == 0
|
assert len(events) == 0
|
||||||
|
|
||||||
|
def test_wait_template(self):
|
||||||
|
"""Test the wait template."""
|
||||||
|
event = 'test_event'
|
||||||
|
events = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def record_event(event):
|
||||||
|
"""Add recorded event to set."""
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
|
self.hass.bus.listen(event, record_event)
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'on')
|
||||||
|
|
||||||
|
script_obj = script.Script(self.hass, cv.SCRIPT_SCHEMA([
|
||||||
|
{'event': event},
|
||||||
|
{'wait_template': "{{states.switch.test.state == 'off'}}"},
|
||||||
|
{'event': event}]))
|
||||||
|
|
||||||
|
script_obj.run()
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
assert script_obj.is_running
|
||||||
|
assert script_obj.can_cancel
|
||||||
|
assert script_obj.last_action == event
|
||||||
|
assert len(events) == 1
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'off')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
assert not script_obj.is_running
|
||||||
|
assert len(events) == 2
|
||||||
|
|
||||||
|
def test_wait_template_cancel(self):
|
||||||
|
"""Test the wait template cancel action."""
|
||||||
|
event = 'test_event'
|
||||||
|
events = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def record_event(event):
|
||||||
|
"""Add recorded event to set."""
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
|
self.hass.bus.listen(event, record_event)
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'on')
|
||||||
|
|
||||||
|
script_obj = script.Script(self.hass, cv.SCRIPT_SCHEMA([
|
||||||
|
{'event': event},
|
||||||
|
{'wait_template': "{{states.switch.test.state == 'off'}}"},
|
||||||
|
{'event': event}]))
|
||||||
|
|
||||||
|
script_obj.run()
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
assert script_obj.is_running
|
||||||
|
assert script_obj.can_cancel
|
||||||
|
assert script_obj.last_action == event
|
||||||
|
assert len(events) == 1
|
||||||
|
|
||||||
|
script_obj.stop()
|
||||||
|
|
||||||
|
assert not script_obj.is_running
|
||||||
|
assert len(events) == 1
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'off')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
assert not script_obj.is_running
|
||||||
|
assert len(events) == 1
|
||||||
|
|
||||||
|
def test_wait_template_not_schedule(self):
|
||||||
|
"""Test the wait template with correct condition."""
|
||||||
|
event = 'test_event'
|
||||||
|
events = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def record_event(event):
|
||||||
|
"""Add recorded event to set."""
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
|
self.hass.bus.listen(event, record_event)
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'on')
|
||||||
|
|
||||||
|
script_obj = script.Script(self.hass, cv.SCRIPT_SCHEMA([
|
||||||
|
{'event': event},
|
||||||
|
{'wait_template': "{{states.switch.test.state == 'on'}}"},
|
||||||
|
{'event': event}]))
|
||||||
|
|
||||||
|
script_obj.run()
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
assert not script_obj.is_running
|
||||||
|
assert script_obj.can_cancel
|
||||||
|
assert len(events) == 2
|
||||||
|
|
||||||
|
def test_wait_template_timeout(self):
|
||||||
|
"""Test the wait template."""
|
||||||
|
event = 'test_event'
|
||||||
|
events = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def record_event(event):
|
||||||
|
"""Add recorded event to set."""
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
|
self.hass.bus.listen(event, record_event)
|
||||||
|
|
||||||
|
self.hass.states.set('switch.test', 'on')
|
||||||
|
|
||||||
|
script_obj = script.Script(self.hass, cv.SCRIPT_SCHEMA([
|
||||||
|
{'event': event},
|
||||||
|
{
|
||||||
|
'wait_template': "{{states.switch.test.state == 'off'}}",
|
||||||
|
'timeout': 5
|
||||||
|
},
|
||||||
|
{'event': event}]))
|
||||||
|
|
||||||
|
script_obj.run()
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
assert script_obj.is_running
|
||||||
|
assert script_obj.can_cancel
|
||||||
|
assert script_obj.last_action == event
|
||||||
|
assert len(events) == 1
|
||||||
|
|
||||||
|
future = dt_util.utcnow() + timedelta(seconds=5)
|
||||||
|
fire_time_changed(self.hass, future)
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
assert not script_obj.is_running
|
||||||
|
assert len(events) == 1
|
||||||
|
|
||||||
def test_passing_variables_to_script(self):
|
def test_passing_variables_to_script(self):
|
||||||
"""Test if we can pass variables to script."""
|
"""Test if we can pass variables to script."""
|
||||||
calls = []
|
calls = []
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue