Add ability to use sun as condition in automation

This commit is contained in:
Philip Lundrigan 2015-12-21 16:09:27 -07:00
parent 07fb4ff243
commit 8c010c8df4

View File

@ -17,6 +17,10 @@ DEPENDENCIES = ['sun']
CONF_OFFSET = 'offset'
CONF_EVENT = 'event'
CONF_BEFORE = "before"
CONF_BEFORE_OFFSET = "before_offset"
CONF_AFTER = "after"
CONF_AFTER_OFFSET = "after_offset"
EVENT_SUNSET = 'sunset'
EVENT_SUNRISE = 'sunrise'
@ -37,26 +41,9 @@ def trigger(hass, config, action):
_LOGGER.error("Invalid value for %s: %s", CONF_EVENT, event)
return False
if CONF_OFFSET in config:
raw_offset = config.get(CONF_OFFSET)
negative_offset = False
if raw_offset.startswith('-'):
negative_offset = True
raw_offset = raw_offset[1:]
try:
(hour, minute, second) = [int(x) for x in raw_offset.split(':')]
except ValueError:
_LOGGER.error('Could not parse offset %s', raw_offset)
return False
offset = timedelta(hours=hour, minutes=minute, seconds=second)
if negative_offset:
offset *= -1
else:
offset = timedelta(0)
offset = _parse_offset(config.get(CONF_OFFSET))
if offset is False:
return False
# Do something to call action
if event == EVENT_SUNRISE:
@ -67,6 +54,70 @@ def trigger(hass, config, action):
return True
def if_action(hass, config):
""" Wraps action method with sun based condition. """
before = config.get(CONF_BEFORE)
after = config.get(CONF_AFTER)
# Make sure required configuration keys are present
if before is None and after is None:
logging.getLogger(__name__).error(
"Missing if-condition configuration key %s or %s",
CONF_BEFORE, CONF_AFTER)
return None
# Make sure configuration keys have the right value
if before is not None and before not in (EVENT_SUNRISE, EVENT_SUNSET) or \
after is not None and after not in (EVENT_SUNRISE, EVENT_SUNSET):
logging.getLogger(__name__).error(
"%s and %s can only be set to %s or %s",
CONF_BEFORE, CONF_AFTER, EVENT_SUNRISE, EVENT_SUNSET)
return None
before_offset = _parse_offset(config.get(CONF_BEFORE_OFFSET))
after_offset = _parse_offset(config.get(CONF_AFTER_OFFSET))
if before_offset is False or after_offset is False:
return None
if before is None:
before_func = lambda: None
elif before == EVENT_SUNRISE:
before_func = lambda: sun.next_rising_utc(hass) + before_offset
else:
before_func = lambda: sun.next_setting_utc(hass) + before_offset
if after is None:
after_func = lambda: None
elif after == EVENT_SUNRISE:
after_func = lambda: sun.next_rising_utc(hass) + after_offset
else:
after_func = lambda: sun.next_setting_utc(hass) + after_offset
# This is needed for testing
time_func = dt_util.utcnow
def time_if():
""" Validate time based if-condition """
# This is needed for testing.
nonlocal time_func
now = time_func()
before = before_func()
after = after_func()
if before is not None and now > now.replace(hour=before.hour,
minute=before.minute):
return False
if after is not None and now < now.replace(hour=after.hour,
minute=after.minute):
return False
return True
return time_if
def trigger_sunrise(hass, action, offset):
""" Trigger action at next sun rise. """
def next_rise():
@ -103,3 +154,26 @@ def trigger_sunset(hass, action, offset):
action()
track_point_in_utc_time(hass, sunset_automation_listener, next_set())
def _parse_offset(raw_offset):
if raw_offset is None:
return timedelta(0)
negative_offset = False
if raw_offset.startswith('-'):
negative_offset = True
raw_offset = raw_offset[1:]
try:
(hour, minute, second) = [int(x) for x in raw_offset.split(':')]
except ValueError:
_LOGGER.error('Could not parse offset %s', raw_offset)
return False
offset = timedelta(hours=hour, minutes=minute, seconds=second)
if negative_offset:
offset *= -1
return offset