Allow wait template to run the remainder of the script (#15836)

* Adding new feature to allow a wait template to run the remainer of the script on timeout

* Styling changes

* Fixing file permissions, adding test for new code

* changed variable name, refactored script to pass information into async_set_timeout

* Changing the default behaviour to continue to run the script after timeout
pull/14257/merge
Hovo (Luke) 2018-08-13 19:23:27 +10:00 committed by Paulus Schoutsen
parent 2342709803
commit 6aee535d7c
3 changed files with 94 additions and 9 deletions

View File

@ -613,6 +613,7 @@ _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),
vol.Optional("continue_on_timeout"): boolean,
})
SCRIPT_SCHEMA = vol.All(

View File

@ -30,6 +30,7 @@ CONF_EVENT_DATA = 'event_data'
CONF_EVENT_DATA_TEMPLATE = 'event_data_template'
CONF_DELAY = 'delay'
CONF_WAIT_TEMPLATE = 'wait_template'
CONF_CONTINUE = 'continue_on_timeout'
def call_from_config(hass: HomeAssistant, config: ConfigType,
@ -143,7 +144,8 @@ class Script():
self.hass.async_add_job(self._change_listener)
if CONF_TIMEOUT in action:
self._async_set_timeout(action, variables)
self._async_set_timeout(
action, variables, action.get(CONF_CONTINUE, True))
return
@ -214,17 +216,23 @@ class Script():
self._log("Test condition {}: {}".format(self.last_action, check))
return check
def _async_set_timeout(self, action, variables):
"""Schedule a timeout to abort script."""
def _async_set_timeout(self, action, variables, continue_on_timeout=True):
"""Schedule a timeout to abort or continue script."""
timeout = action[CONF_TIMEOUT]
unsub = None
@callback
def async_script_timeout(now):
"""Call after timeout is retrieve stop script."""
"""Call after timeout is retrieve."""
self._async_listener.remove(unsub)
self._log("Timeout reached, abort script.")
self.async_stop()
# Check if we want to continue to execute
# the script after the timeout
if continue_on_timeout:
self.hass.async_add_job(self.async_run(variables))
else:
self._log("Timeout reached, abort script.")
self.async_stop()
unsub = async_track_point_in_utc_time(
self.hass, async_script_timeout,

View File

@ -375,8 +375,84 @@ class TestScriptHelper(unittest.TestCase):
assert script_obj.can_cancel
assert len(events) == 2
def test_wait_template_timeout(self):
"""Test the wait template."""
def test_wait_template_timeout_halt(self):
"""Test the wait template, halt on timeout."""
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'}}",
'continue_on_timeout': False,
'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_wait_template_timeout_continue(self):
"""Test the wait template with continuing the script."""
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,
'continue_on_timeout': True
},
{'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) == 2
def test_wait_template_timeout_default(self):
"""Test the wait template with default contiune."""
event = 'test_event'
events = []
@ -410,7 +486,7 @@ class TestScriptHelper(unittest.TestCase):
self.hass.block_till_done()
assert not script_obj.is_running
assert len(events) == 1
assert len(events) == 2
def test_wait_template_variables(self):
"""Test the wait template with variables."""