Merge pull request #1002 from kennedyshead/dev

Running periodic tasks
This commit is contained in:
Paulus Schoutsen 2016-01-26 21:42:06 -08:00
commit 886b581d2a
5 changed files with 178 additions and 6 deletions

1
.gitignore vendored
View File

@ -77,6 +77,7 @@ nosetests.xml
# venv stuff
pyvenv.cfg
pip-selfcheck.json
venv
# vimmy stuff
*.swp

View File

@ -8,7 +8,6 @@ at https://home-assistant.io/components/automation/#time-trigger
"""
import logging
from homeassistant.util import convert
import homeassistant.util.dt as dt_util
from homeassistant.helpers.event import track_time_change
@ -34,9 +33,9 @@ def trigger(hass, config, action):
hours, minutes, seconds = after.hour, after.minute, after.second
elif (CONF_HOURS in config or CONF_MINUTES in config or
CONF_SECONDS in config):
hours = convert(config.get(CONF_HOURS), int)
minutes = convert(config.get(CONF_MINUTES), int)
seconds = convert(config.get(CONF_SECONDS), int)
hours = config.get(CONF_HOURS)
minutes = config.get(CONF_MINUTES)
seconds = config.get(CONF_SECONDS)
else:
_LOGGER.error('One of %s, %s, %s OR %s needs to be specified',
CONF_HOURS, CONF_MINUTES, CONF_SECONDS, CONF_AFTER)
@ -59,7 +58,7 @@ def if_action(hass, config):
weekday = config.get(CONF_WEEKDAY)
if before is None and after is None and weekday is None:
logging.getLogger(__name__).error(
_LOGGER.error(
"Missing if-condition configuration key %s, %s or %s",
CONF_BEFORE, CONF_AFTER, CONF_WEEKDAY)
return None

View File

@ -170,7 +170,6 @@ def track_utc_time_change(hass, action, year=None, month=None, day=None,
if local:
now = dt_util.as_local(now)
mat = _matcher
# pylint: disable=too-many-boolean-expressions
@ -199,6 +198,8 @@ def _process_match_param(parameter):
""" Wraps parameter in a tuple if it is not one and returns it. """
if parameter is None or parameter == MATCH_ALL:
return MATCH_ALL
elif isinstance(parameter, str) and parameter.startswith('/'):
return parameter
elif isinstance(parameter, str) or not hasattr(parameter, '__iter__'):
return (parameter,)
else:
@ -210,4 +211,10 @@ def _matcher(subject, pattern):
Pattern is either a tuple of allowed subjects or a `MATCH_ALL`.
"""
if isinstance(pattern, str) and pattern.startswith('/'):
try:
return subject % float(pattern.lstrip('/')) == 0
except ValueError:
return False
return MATCH_ALL == pattern or subject in pattern

View File

@ -301,6 +301,63 @@ class TestAutomationTime(unittest.TestCase):
self.hass.pool.block_till_done()
self.assertEqual(1, len(self.calls))
def test_if_fires_periodic_seconds(self):
self.assertTrue(automation.setup(self.hass, {
automation.DOMAIN: {
'trigger': {
'platform': 'time',
'seconds': "/2",
},
'action': {
'service': 'test.automation'
}
}
}))
fire_time_changed(self.hass, dt_util.utcnow().replace(
hour=0, minute=0, second=2))
self.hass.pool.block_till_done()
self.assertEqual(1, len(self.calls))
def test_if_fires_periodic_minutes(self):
self.assertTrue(automation.setup(self.hass, {
automation.DOMAIN: {
'trigger': {
'platform': 'time',
'minutes': "/2",
},
'action': {
'service': 'test.automation'
}
}
}))
fire_time_changed(self.hass, dt_util.utcnow().replace(
hour=0, minute=2, second=0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(self.calls))
def test_if_fires_periodic_hours(self):
self.assertTrue(automation.setup(self.hass, {
automation.DOMAIN: {
'trigger': {
'platform': 'time',
'hours': "/2",
},
'action': {
'service': 'test.automation'
}
}
}))
fire_time_changed(self.hass, dt_util.utcnow().replace(
hour=2, minute=0, second=0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(self.calls))
def test_if_fires_using_after(self):
self.assertTrue(automation.setup(self.hass, {
automation.DOMAIN: {
@ -320,6 +377,24 @@ class TestAutomationTime(unittest.TestCase):
self.hass.pool.block_till_done()
self.assertEqual(1, len(self.calls))
def test_if_not_working_if_no_values_in_conf_provided(self):
self.assertTrue(automation.setup(self.hass, {
automation.DOMAIN: {
'trigger': {
'platform': 'time',
},
'action': {
'service': 'test.automation'
}
}
}))
fire_time_changed(self.hass, dt_util.utcnow().replace(
hour=5, minute=0, second=0))
self.hass.pool.block_till_done()
self.assertEqual(0, len(self.calls))
@patch('homeassistant.components.automation.time._LOGGER.error')
def test_if_not_fires_using_wrong_after(self, mock_error):
""" YAML translates time values to total seconds. This should break the

View File

@ -219,3 +219,93 @@ class TestEventHelpers(unittest.TestCase):
def _send_time_changed(self, now):
""" Send a time changed event. """
self.hass.bus.fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: now})
def test_periodic_task_minute(self):
specific_runs = []
track_utc_time_change(
self.hass, lambda x: specific_runs.append(1), minute='/5')
self._send_time_changed(datetime(2014, 5, 24, 12, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(specific_runs))
self._send_time_changed(datetime(2014, 5, 24, 12, 3, 0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(specific_runs))
self._send_time_changed(datetime(2014, 5, 24, 12, 5, 0))
self.hass.pool.block_till_done()
self.assertEqual(2, len(specific_runs))
def test_periodic_task_hour(self):
specific_runs = []
track_utc_time_change(
self.hass, lambda x: specific_runs.append(1), hour='/2')
self._send_time_changed(datetime(2014, 5, 24, 22, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(specific_runs))
self._send_time_changed(datetime(2014, 5, 24, 23, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(specific_runs))
self._send_time_changed(datetime(2014, 5, 24, 0, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(2, len(specific_runs))
self._send_time_changed(datetime(2014, 5, 25, 1, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(2, len(specific_runs))
self._send_time_changed(datetime(2014, 5, 25, 2, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(3, len(specific_runs))
def test_periodic_task_day(self):
specific_runs = []
track_utc_time_change(
self.hass, lambda x: specific_runs.append(1), day='/2')
self._send_time_changed(datetime(2014, 5, 2, 0, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(specific_runs))
self._send_time_changed(datetime(2014, 5, 3, 12, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(specific_runs))
self._send_time_changed(datetime(2014, 5, 4, 0, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(2, len(specific_runs))
def test_periodic_task_year(self):
specific_runs = []
track_utc_time_change(
self.hass, lambda x: specific_runs.append(1), year='/2')
self._send_time_changed(datetime(2014, 5, 2, 0, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(specific_runs))
self._send_time_changed(datetime(2015, 5, 2, 0, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(1, len(specific_runs))
self._send_time_changed(datetime(2016, 5, 2, 0, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(2, len(specific_runs))
def test_periodic_task_wrong_input(self):
specific_runs = []
track_utc_time_change(
self.hass, lambda x: specific_runs.append(1), year='/two')
self._send_time_changed(datetime(2014, 5, 2, 0, 0, 0))
self.hass.pool.block_till_done()
self.assertEqual(0, len(specific_runs))