149 lines
4.2 KiB
Python
149 lines
4.2 KiB
Python
"""
|
|
homeassistant.components.automation.sun
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
Offers sun based automation rules.
|
|
|
|
For more details about this automation rule, please refer to the documentation
|
|
at https://home-assistant.io/components/automation/#sun-trigger
|
|
"""
|
|
import logging
|
|
from datetime import timedelta
|
|
|
|
from homeassistant.components import sun
|
|
from homeassistant.helpers.event import track_sunrise, track_sunset
|
|
import homeassistant.util.dt as dt_util
|
|
|
|
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'
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
def trigger(hass, config, action):
|
|
""" Listen for events based on config. """
|
|
event = config.get(CONF_EVENT)
|
|
|
|
if event is None:
|
|
_LOGGER.error("Missing configuration key %s", CONF_EVENT)
|
|
return False
|
|
|
|
event = event.lower()
|
|
if event not in (EVENT_SUNRISE, EVENT_SUNSET):
|
|
_LOGGER.error("Invalid value for %s: %s", CONF_EVENT, event)
|
|
return False
|
|
|
|
offset = _parse_offset(config.get(CONF_OFFSET))
|
|
if offset is False:
|
|
return False
|
|
|
|
# Do something to call action
|
|
if event == EVENT_SUNRISE:
|
|
track_sunrise(hass, action, offset)
|
|
else:
|
|
track_sunset(hass, action, offset)
|
|
|
|
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 not in (None, EVENT_SUNRISE, EVENT_SUNSET) or \
|
|
after not in (None, 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:
|
|
def before_func():
|
|
"""Return no point in time."""
|
|
return None
|
|
elif before == EVENT_SUNRISE:
|
|
def before_func():
|
|
"""Return time before sunrise."""
|
|
return sun.next_rising(hass) + before_offset
|
|
else:
|
|
def before_func():
|
|
"""Return time before sunset."""
|
|
return sun.next_setting(hass) + before_offset
|
|
|
|
if after is None:
|
|
def after_func():
|
|
"""Return no point in time."""
|
|
return None
|
|
elif after == EVENT_SUNRISE:
|
|
def after_func():
|
|
"""Return time after sunrise."""
|
|
return sun.next_rising(hass) + after_offset
|
|
else:
|
|
def after_func():
|
|
"""Return time after sunset."""
|
|
return sun.next_setting(hass) + after_offset
|
|
|
|
def time_if():
|
|
""" Validate time based if-condition """
|
|
|
|
now = dt_util.now()
|
|
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 _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
|