Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions homeassistant/helpers/config_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ def validator(value):
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(
Expand Down
20 changes: 14 additions & 6 deletions homeassistant/helpers/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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,
Expand Down Expand Up @@ -143,7 +144,8 @@ def async_script_wait(entity_id, from_s, to_s):
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, False))

return

Expand Down Expand Up @@ -214,17 +216,23 @@ def _async_check_condition(self, action, variables):
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=False):
"""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,
Expand Down
38 changes: 38 additions & 0 deletions tests/helpers/test_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,44 @@ def record_event(event):
assert not script_obj.is_running
assert len(events) == 1

def test_wait_template_timeout_continue(self):
"""Test the wait template with proceed."""
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_variables(self):
"""Test the wait template with variables."""
event = 'test_event'
Expand Down