diff --git a/homeassistant/components/scheduler/__init__.py b/homeassistant/components/scheduler/__init__.py index c06f6acd7f5..120f90b6ccf 100644 --- a/homeassistant/components/scheduler/__init__.py +++ b/homeassistant/components/scheduler/__init__.py @@ -18,27 +18,44 @@ entity_ids, and events. import logging import json +from homeassistant import bootstrap from homeassistant.loader import get_component - from homeassistant.const import ATTR_ENTITY_ID # The domain of your component. Should be equal to the name of your component DOMAIN = 'scheduler' -# List of component names (string) your component depends upon -# If you are setting up a group but not using a group for anything, -# don't depend on group -DEPENDENCIES = ['sun'] +DEPENDENCIES = [] _LOGGER = logging.getLogger(__name__) _SCHEDULE_FILE = 'schedule.json' -# pylint: disable=unused-argument def setup(hass, config): """ Create the schedules """ + if DOMAIN in hass.components: + return True + + def setup_listener(schedule, event_data): + """ Creates the event listener based on event_data """ + event_type = event_data['type'] + component = event_type + + # if the event isn't part of a component + if event_type in ['time']: + component = 'scheduler.{}'.format(event_type) + + elif component not in hass.components and \ + not bootstrap.setup_component(hass, component, config): + + _LOGGER.warn("Could setup event listener for %s", component) + return None + + return get_component(component).create_event_listener(schedule, + event_data) + def setup_schedule(schedule_data): """ setup a schedule based on the description """ @@ -49,10 +66,10 @@ def setup(hass, config): days=schedule_data['days']) for event_data in schedule_data['events']: - event_listener_type = \ - get_component('scheduler.{}'.format(event_data['type'])) - event_listener = event_listener_type.create(schedule, event_data) - schedule.add_event_listener(event_listener) + event_listener = setup_listener(schedule, event_data) + + if event_listener: + schedule.add_event_listener(event_listener) schedule.schedule(hass) return True diff --git a/homeassistant/components/scheduler/sun.py b/homeassistant/components/scheduler/sun.py deleted file mode 100644 index 5af965a1764..00000000000 --- a/homeassistant/components/scheduler/sun.py +++ /dev/null @@ -1,114 +0,0 @@ -""" -An event in the scheduler component that will call the service -when the sun rises or sets with an offset. -The sun evnt need to have the type 'sun', which service to call, -which event (sunset or sunrise) and the offset. - -{ - "type": "sun", - "service": "switch.turn_on", - "event": "sunset", - "offset": "-01:00:00" -} - -""" - -from datetime import datetime, timedelta -import logging - -from homeassistant.components.scheduler import ServiceEventListener -import homeassistant.components.sun as sun - -_LOGGER = logging.getLogger(__name__) - - -def create(schedule, event_listener_data): - """ Create a sun event listener based on the description. """ - - negative_offset = False - service = event_listener_data['service'] - offset_str = event_listener_data['offset'] - event = event_listener_data['event'] - - if offset_str.startswith('-'): - negative_offset = True - offset_str = offset_str[1:] - - (hour, minute, second) = [int(x) for x in offset_str.split(':')] - - offset = timedelta(hours=hour, minutes=minute, seconds=second) - - if event == 'sunset': - return SunsetEventListener(schedule, service, offset, negative_offset) - - return SunriseEventListener(schedule, service, offset, negative_offset) - - -# pylint: disable=too-few-public-methods -class SunEventListener(ServiceEventListener): - """ This is the base class for sun event listeners. """ - - def __init__(self, schedule, service, offset, negative_offset): - ServiceEventListener.__init__(self, schedule, service) - - self.offset = offset - self.negative_offset = negative_offset - - def __get_next_time(self, next_event): - """ - Returns when the next time the service should be called. - Taking into account the offset and which days the event should execute. - """ - - if self.negative_offset: - next_time = next_event - self.offset - else: - next_time = next_event + self.offset - - while next_time < datetime.now() or \ - next_time.weekday() not in self.my_schedule.days: - next_time = next_time + timedelta(days=1) - - return next_time - - def schedule_next_event(self, hass, next_event): - """ Schedule the event """ - next_time = self.__get_next_time(next_event) - - # pylint: disable=unused-argument - def execute(now): - """ Call the execute method """ - self.execute(hass) - - hass.track_point_in_time(execute, next_time) - - return next_time - - -# pylint: disable=too-few-public-methods -class SunsetEventListener(SunEventListener): - """ This class is used the call a service when the sun sets. """ - def schedule(self, hass): - """ Schedule the event """ - next_setting = sun.next_setting(hass) - - next_time = self.schedule_next_event(hass, next_setting) - - _LOGGER.info( - 'SunsetEventListener scheduled for %s, will call service %s.%s', - next_time, self.domain, self.service) - - -# pylint: disable=too-few-public-methods -class SunriseEventListener(SunEventListener): - """ This class is used the call a service when the sun rises. """ - - def schedule(self, hass): - """ Schedule the event """ - next_rising = sun.next_rising(hass) - - next_time = self.schedule_next_event(hass, next_rising) - - _LOGGER.info( - 'SunriseEventListener scheduled for %s, will call service %s.%s', - next_time, self.domain, self.service) diff --git a/homeassistant/components/scheduler/time.py b/homeassistant/components/scheduler/time.py index c1d8ebb7845..90fa495cee2 100644 --- a/homeassistant/components/scheduler/time.py +++ b/homeassistant/components/scheduler/time.py @@ -20,7 +20,7 @@ from homeassistant.components.scheduler import ServiceEventListener _LOGGER = logging.getLogger(__name__) -def create(schedule, event_listener_data): +def create_event_listener(schedule, event_listener_data): """ Create a TimeEvent based on the description """ service = event_listener_data['service'] diff --git a/homeassistant/components/sun.py b/homeassistant/components/sun.py index c6bacb45f87..456ec7e385b 100644 --- a/homeassistant/components/sun.py +++ b/homeassistant/components/sun.py @@ -3,6 +3,23 @@ homeassistant.components.sun ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Provides functionality to keep track of the sun. + + +Event listener +-------------- +The suns event listener will call the service +when the sun rises or sets with an offset. +The sun evnt need to have the type 'sun', which service to call, +which event (sunset or sunrise) and the offset. + +{ + "type": "sun", + "service": "switch.turn_on", + "event": "sunset", + "offset": "-01:00:00" +} + + """ import logging from datetime import datetime, timedelta @@ -12,6 +29,8 @@ from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE from homeassistant.helpers import validate_config from homeassistant.util import str_to_datetime, datetime_to_str +from homeassistant.components.scheduler import ServiceEventListener + DEPENDENCIES = [] DOMAIN = "sun" ENTITY_ID = "sun.sun" @@ -22,6 +41,8 @@ STATE_BELOW_HORIZON = "below_horizon" STATE_ATTR_NEXT_RISING = "next_rising" STATE_ATTR_NEXT_SETTING = "next_setting" +_LOGGER = logging.getLogger(__name__) + def is_on(hass, entity_id=None): """ Returns if the sun is currently up based on the statemachine. """ @@ -137,3 +158,95 @@ def setup(hass, config): update_sun_state(datetime.now()) return True + + +def create_event_listener(schedule, event_listener_data): + """ Create a sun event listener based on the description. """ + + negative_offset = False + service = event_listener_data['service'] + offset_str = event_listener_data['offset'] + event = event_listener_data['event'] + + if offset_str.startswith('-'): + negative_offset = True + offset_str = offset_str[1:] + + (hour, minute, second) = [int(x) for x in offset_str.split(':')] + + offset = timedelta(hours=hour, minutes=minute, seconds=second) + + if event == 'sunset': + return SunsetEventListener(schedule, service, offset, negative_offset) + + return SunriseEventListener(schedule, service, offset, negative_offset) + + +# pylint: disable=too-few-public-methods +class SunEventListener(ServiceEventListener): + """ This is the base class for sun event listeners. """ + + def __init__(self, schedule, service, offset, negative_offset): + ServiceEventListener.__init__(self, schedule, service) + + self.offset = offset + self.negative_offset = negative_offset + + def __get_next_time(self, next_event): + """ + Returns when the next time the service should be called. + Taking into account the offset and which days the event should execute. + """ + + if self.negative_offset: + next_time = next_event - self.offset + else: + next_time = next_event + self.offset + + while next_time < datetime.now() or \ + next_time.weekday() not in self.my_schedule.days: + next_time = next_time + timedelta(days=1) + + return next_time + + def schedule_next_event(self, hass, next_event): + """ Schedule the event """ + next_time = self.__get_next_time(next_event) + + # pylint: disable=unused-argument + def execute(now): + """ Call the execute method """ + self.execute(hass) + + hass.track_point_in_time(execute, next_time) + + return next_time + + +# pylint: disable=too-few-public-methods +class SunsetEventListener(SunEventListener): + """ This class is used the call a service when the sun sets. """ + def schedule(self, hass): + """ Schedule the event """ + next_setting_dt = next_setting(hass) + + next_time_dt = self.schedule_next_event(hass, next_setting_dt) + + _LOGGER.info( + 'SunsetEventListener scheduled for %s, will call service %s.%s', + next_time_dt, self.domain, self.service) + + +# pylint: disable=too-few-public-methods +class SunriseEventListener(SunEventListener): + """ This class is used the call a service when the sun rises. """ + + def schedule(self, hass): + """ Schedule the event """ + next_rising_dt = next_rising(hass) + + next_time_dt = self.schedule_next_event(hass, next_rising_dt) + + _LOGGER.info( + 'SunriseEventListener scheduled for %s, will call service %s.%s', + next_time_dt, self.domain, self.service)