From aab52ca686705c50c8360c8707f9811ff8fcb3b0 Mon Sep 17 00:00:00 2001 From: Gustav Ahlberg Date: Mon, 17 Nov 2014 21:18:01 +0100 Subject: [PATCH 1/9] Schedule component Can read schedule json config file Can load custom rule_types --- .../components/scheduler/__init__.py | 50 +++++++++++++++++++ homeassistant/components/scheduler/sun.py | 5 ++ homeassistant/components/scheduler/time.py | 5 ++ 3 files changed, 60 insertions(+) create mode 100644 homeassistant/components/scheduler/__init__.py create mode 100644 homeassistant/components/scheduler/sun.py create mode 100644 homeassistant/components/scheduler/time.py diff --git a/homeassistant/components/scheduler/__init__.py b/homeassistant/components/scheduler/__init__.py new file mode 100644 index 00000000000..de950d03a47 --- /dev/null +++ b/homeassistant/components/scheduler/__init__.py @@ -0,0 +1,50 @@ +""" +homeassistant.components.scheduler +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +""" +import logging +from datetime import datetime, timedelta +import json +from pprint import pprint +import importlib + +from homeassistant.components import switch, sun +from homeassistant.loader import get_component + +# 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'] + +_LOGGER = logging.getLogger(__name__) + +_SCHEDULE_FILE = 'schedule.json' +_RULE_TYPE_CACHE = {} + + +# pylint: disable=unused-argument +def setup(hass, config): + """ Register services or listen for events that your component needs. """ + + def setup_schedule(description): + + for rule in description['rules']: + rule_init = get_component('scheduler.{}'.format(rule['type'])) + + if rule_init is None: + _LOGGER.error('Error loading schedule rule %s', rule['type']) + return False + + return True + + with open(hass.get_config_path(_SCHEDULE_FILE)) as schedule_file: + schedule_descriptions = json.load(schedule_file) + + for schedule_description in schedule_descriptions: + if not setup_schedule(schedule_description): + return False + + return True diff --git a/homeassistant/components/scheduler/sun.py b/homeassistant/components/scheduler/sun.py new file mode 100644 index 00000000000..6ab66e7a36c --- /dev/null +++ b/homeassistant/components/scheduler/sun.py @@ -0,0 +1,5 @@ +"""asd""" + + +def hej(): + print('wut sun wut') diff --git a/homeassistant/components/scheduler/time.py b/homeassistant/components/scheduler/time.py new file mode 100644 index 00000000000..348f6537bc6 --- /dev/null +++ b/homeassistant/components/scheduler/time.py @@ -0,0 +1,5 @@ +"""asd""" + + +def hej(): + print('wut wut') From 1c94bb1c0f935125b4ba504c56068a1bac8d729d Mon Sep 17 00:00:00 2001 From: Gustav Ahlberg Date: Wed, 26 Nov 2014 19:28:36 +0100 Subject: [PATCH 2/9] Schedule component and time event The schedule can read a schedule.json file and create time events --- .../components/scheduler/__init__.py | 80 ++++++++++++++++--- homeassistant/components/scheduler/sun.py | 6 +- homeassistant/components/scheduler/time.py | 75 ++++++++++++++++- 3 files changed, 145 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/scheduler/__init__.py b/homeassistant/components/scheduler/__init__.py index de950d03a47..1894d9eb8bf 100644 --- a/homeassistant/components/scheduler/__init__.py +++ b/homeassistant/components/scheduler/__init__.py @@ -1,14 +1,25 @@ """ homeassistant.components.scheduler ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A component that will act as a scheduler and performe actions based +on the events in the schedule. + +It will read a json object from schedule.json in the config dir +and create a schedule based on it. +Each schedule is a JSON with the keys id, name, description, +entity_ids, and events. +- days is an array with the weekday number (monday=0) that the schdule + is active +- entity_ids an array with entity ids that the events in the schedule should + effect (can also be groups) +- events is an array of objects that describe the different events that is + supported. Read in the events descriptions for more information """ import logging -from datetime import datetime, timedelta import json -from pprint import pprint import importlib -from homeassistant.components import switch, sun +from homeassistant.components import switch from homeassistant.loader import get_component # The domain of your component. Should be equal to the name of your component @@ -17,27 +28,33 @@ 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' -_RULE_TYPE_CACHE = {} # pylint: disable=unused-argument def setup(hass, config): - """ Register services or listen for events that your component needs. """ + """ Create the schedules """ def setup_schedule(description): + """ setup a schedule based on the description """ - for rule in description['rules']: - rule_init = get_component('scheduler.{}'.format(rule['type'])) + schedule = Schedule(hass, description['id'], + name=description['name'], + description=description['description'], + entity_ids=description['entity_ids'], + days=description['days']) - if rule_init is None: - _LOGGER.error('Error loading schedule rule %s', rule['type']) - return False + for event_description in description['events']: + event_type = \ + get_component('scheduler.{}'.format(event_description['type'])) + event = event_type.create(schedule, event_description) + schedule.add_event(event) + schedule.schedule() return True with open(hass.get_config_path(_SCHEDULE_FILE)) as schedule_file: @@ -48,3 +65,44 @@ def setup(hass, config): return False return True + + +class Schedule(object): + """ A Schedule """ + def __init__(self, hass, schedule_id, name=None, description=None, + entity_ids=None, days=None): + + self.hass = hass + + self.schedule_id = schedule_id + self.name = name + self.description = description + + self.entity_ids = entity_ids or [] + + self.days = days or [0, 1, 2, 3, 4, 5, 6] + + self._events = [] + + def add_event(self, event): + """ Add a event to the schedule """ + self._events.append(event) + + def schedule(self): + """ Schedule all the events in the schdule """ + for event in self._events: + event.schedule() + + +class Event(object): + """ The base Event class that the schedule uses """ + def __init__(self, schedule): + self._schedule = schedule + + def schedule(self): + """ Schedule the event """ + pass + + def execute(self): + """ execute the event """ + pass diff --git a/homeassistant/components/scheduler/sun.py b/homeassistant/components/scheduler/sun.py index 6ab66e7a36c..074f2bc0705 100644 --- a/homeassistant/components/scheduler/sun.py +++ b/homeassistant/components/scheduler/sun.py @@ -1,5 +1,7 @@ """asd""" +from homeassistant.components.scheduler import Event -def hej(): - print('wut sun wut') + +def create(schedule, description): + print('creating sun') diff --git a/homeassistant/components/scheduler/time.py b/homeassistant/components/scheduler/time.py index 348f6537bc6..14081c25a5f 100644 --- a/homeassistant/components/scheduler/time.py +++ b/homeassistant/components/scheduler/time.py @@ -1,5 +1,74 @@ -"""asd""" +""" +An event in the scheduler component that will call the service +every specified day at the time specified. +A time event need to have the type 'time', which service to call and at +which time. + +{ + "type": "time", + "service": "switch.turn_off", + "time": "22:00" +} + +""" + +from datetime import datetime, timedelta +import logging + +from homeassistant.components.scheduler import Event + +_LOGGER = logging.getLogger(__name__) -def hej(): - print('wut wut') +def create(schedule, description): + """ Create a TimeEvent based on the description """ + + service = description['service'] + (hour, minute) = [int(x) for x in description['time'].split(':')] + + return TimeEvent(schedule, service, hour, minute) + + +class TimeEvent(Event): + """ The time event that the scheduler uses """ + + def __init__(self, schedule, service, hour, minute): + Event.__init__(self, schedule) + + (self._domain, self._service) = service.split('.') + + self._hour = hour + self._minute = minute + + print(self._domain, self._service) + + def schedule(self): + """ Schedule this event so that it will be called """ + + next_time = datetime.now().replace(hour=self._hour, + minute=self._minute, + second=0, microsecond=0) + + # Calculate the next time the event should be executed. + # That is the next day that the schedule is configured to run + while next_time < datetime.now() or \ + next_time.weekday() not in self._schedule.days: + + next_time = next_time + timedelta(days=1) + + # pylint: disable=unused-argument + def execute(now): + """ Call the execute method """ + self.execute() + + self._schedule.hass.track_point_in_time(execute, next_time) + + _LOGGER.info('point in time scheduled at {} for {}' + .format(next_time, "")) + + def execute(self): + """ Call the service """ + # data = {ATTR_ENTITY_ID: self._schedule.entity_ids} + # self._schedule.hass.call_service(self._domain, self._service, data) + print("executoing time", self._domain, self._service) + self.schedule() From c92089808f31021ed93b95634bf2b2a32b3bb6d3 Mon Sep 17 00:00:00 2001 From: Gustav Ahlberg Date: Wed, 3 Dec 2014 20:29:15 +0100 Subject: [PATCH 3/9] completed time_event_listener --- .../components/scheduler/__init__.py | 46 +++++++++---------- homeassistant/components/scheduler/time.py | 39 ++++++++-------- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/homeassistant/components/scheduler/__init__.py b/homeassistant/components/scheduler/__init__.py index 1894d9eb8bf..19e105e67ba 100644 --- a/homeassistant/components/scheduler/__init__.py +++ b/homeassistant/components/scheduler/__init__.py @@ -39,22 +39,22 @@ _SCHEDULE_FILE = 'schedule.json' def setup(hass, config): """ Create the schedules """ - def setup_schedule(description): + def setup_schedule(schedule_data): """ setup a schedule based on the description """ - schedule = Schedule(hass, description['id'], - name=description['name'], - description=description['description'], - entity_ids=description['entity_ids'], - days=description['days']) + schedule = Schedule(schedule_data['id'], + name=schedule_data['name'], + description=schedule_data['description'], + entity_ids=schedule_data['entity_ids'], + days=schedule_data['days']) - for event_description in description['events']: - event_type = \ - get_component('scheduler.{}'.format(event_description['type'])) - event = event_type.create(schedule, event_description) - schedule.add_event(event) + 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) - schedule.schedule() + schedule.schedule(hass) return True with open(hass.get_config_path(_SCHEDULE_FILE)) as schedule_file: @@ -69,11 +69,9 @@ def setup(hass, config): class Schedule(object): """ A Schedule """ - def __init__(self, hass, schedule_id, name=None, description=None, + def __init__(self, schedule_id, name=None, description=None, entity_ids=None, days=None): - self.hass = hass - self.schedule_id = schedule_id self.name = name self.description = description @@ -82,27 +80,27 @@ class Schedule(object): self.days = days or [0, 1, 2, 3, 4, 5, 6] - self._events = [] + self._event_listeners = [] - def add_event(self, event): + def add_event_listener(self, event_listener): """ Add a event to the schedule """ - self._events.append(event) + self._event_listeners.append(event_listener) - def schedule(self): + def schedule(self, hass): """ Schedule all the events in the schdule """ - for event in self._events: - event.schedule() + for event in self._event_listeners: + event.schedule(hass) -class Event(object): +class EventListener(object): """ The base Event class that the schedule uses """ def __init__(self, schedule): self._schedule = schedule - def schedule(self): + def schedule(self, hass): """ Schedule the event """ pass - def execute(self): + def execute(self, hass): """ execute the event """ pass diff --git a/homeassistant/components/scheduler/time.py b/homeassistant/components/scheduler/time.py index 14081c25a5f..7e737d758f4 100644 --- a/homeassistant/components/scheduler/time.py +++ b/homeassistant/components/scheduler/time.py @@ -15,34 +15,33 @@ which time. from datetime import datetime, timedelta import logging -from homeassistant.components.scheduler import Event +from homeassistant.components.scheduler import EventListener +from homeassistant.components import ATTR_ENTITY_ID _LOGGER = logging.getLogger(__name__) -def create(schedule, description): +def create(schedule, event_listener_data): """ Create a TimeEvent based on the description """ - service = description['service'] - (hour, minute) = [int(x) for x in description['time'].split(':')] + service = event_listener_data['service'] + (hour, minute) = [int(x) for x in event_listener_data['time'].split(':')] - return TimeEvent(schedule, service, hour, minute) + return TimeEventListener(schedule, service, hour, minute) -class TimeEvent(Event): +class TimeEventListener(EventListener): """ The time event that the scheduler uses """ def __init__(self, schedule, service, hour, minute): - Event.__init__(self, schedule) + EventListener.__init__(self, schedule) (self._domain, self._service) = service.split('.') self._hour = hour self._minute = minute - print(self._domain, self._service) - - def schedule(self): + def schedule(self, hass): """ Schedule this event so that it will be called """ next_time = datetime.now().replace(hour=self._hour, @@ -59,16 +58,18 @@ class TimeEvent(Event): # pylint: disable=unused-argument def execute(now): """ Call the execute method """ - self.execute() + self.execute(hass) - self._schedule.hass.track_point_in_time(execute, next_time) + hass.track_point_in_time(execute, next_time) - _LOGGER.info('point in time scheduled at {} for {}' - .format(next_time, "")) + _LOGGER.info( + 'TimeEventListener scheduled for {}, will call service {}.{}' + .format(next_time, self._domain, self._service)) - def execute(self): + def execute(self, hass): """ Call the service """ - # data = {ATTR_ENTITY_ID: self._schedule.entity_ids} - # self._schedule.hass.call_service(self._domain, self._service, data) - print("executoing time", self._domain, self._service) - self.schedule() + data = {ATTR_ENTITY_ID: self._schedule.entity_ids} + hass.call_service(self._domain, self._service, data) + + # Reschedule for next day + self.schedule(hass) From c436b33da9c6d11a93f0c83df44e20d5fb0663bb Mon Sep 17 00:00:00 2001 From: Gustav Ahlberg Date: Sun, 28 Dec 2014 11:29:26 +0100 Subject: [PATCH 4/9] added seconds to timeEventListener --- homeassistant/components/scheduler/time.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/scheduler/time.py b/homeassistant/components/scheduler/time.py index 7e737d758f4..ff4b1940eb0 100644 --- a/homeassistant/components/scheduler/time.py +++ b/homeassistant/components/scheduler/time.py @@ -7,7 +7,7 @@ which time. { "type": "time", "service": "switch.turn_off", - "time": "22:00" + "time": "22:00:00" } """ @@ -25,28 +25,31 @@ def create(schedule, event_listener_data): """ Create a TimeEvent based on the description """ service = event_listener_data['service'] - (hour, minute) = [int(x) for x in event_listener_data['time'].split(':')] + (hour, minute, second) = [int(x) for x in + event_listener_data['time'].split(':')] - return TimeEventListener(schedule, service, hour, minute) + return TimeEventListener(schedule, service, hour, minute, second) class TimeEventListener(EventListener): """ The time event that the scheduler uses """ - def __init__(self, schedule, service, hour, minute): + def __init__(self, schedule, service, hour, minute, second): EventListener.__init__(self, schedule) (self._domain, self._service) = service.split('.') self._hour = hour self._minute = minute + self._second = second def schedule(self, hass): """ Schedule this event so that it will be called """ next_time = datetime.now().replace(hour=self._hour, minute=self._minute, - second=0, microsecond=0) + second=self._second, + microsecond=0) # Calculate the next time the event should be executed. # That is the next day that the schedule is configured to run From 83320681f0c79488e5934075d68e9689d3c0fa17 Mon Sep 17 00:00:00 2001 From: Gustav Ahlberg Date: Sun, 28 Dec 2014 11:29:48 +0100 Subject: [PATCH 5/9] SunriseEventListener and SunsetEventListner --- .../components/scheduler/__init__.py | 20 ++++- homeassistant/components/scheduler/sun.py | 82 ++++++++++++++++++- 2 files changed, 97 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/scheduler/__init__.py b/homeassistant/components/scheduler/__init__.py index 19e105e67ba..451933fa4a4 100644 --- a/homeassistant/components/scheduler/__init__.py +++ b/homeassistant/components/scheduler/__init__.py @@ -28,7 +28,7 @@ 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 = [] +DEPENDENCIES = ['sun'] _LOGGER = logging.getLogger(__name__) @@ -93,7 +93,7 @@ class Schedule(object): class EventListener(object): - """ The base Event class that the schedule uses """ + """ The base EventListner class that the schedule uses """ def __init__(self, schedule): self._schedule = schedule @@ -104,3 +104,19 @@ class EventListener(object): def execute(self, hass): """ execute the event """ pass + +class ServiceEventListener(EventListener): + """ A EventListner that calls a service when executed """ + + def __init__(self, schdule, service): + EventListener.__init__(self, schdule) + + (self._domain, self._service) = service.split('.') + + def execute(self, hass): + """ Call the service """ + data = {ATTR_ENTITY_ID: self._schedule.entity_ids} + hass.call_service(self._domain, self._service, data) + + # Reschedule for next day + self.schedule(hass) diff --git a/homeassistant/components/scheduler/sun.py b/homeassistant/components/scheduler/sun.py index 074f2bc0705..fb76e607c43 100644 --- a/homeassistant/components/scheduler/sun.py +++ b/homeassistant/components/scheduler/sun.py @@ -1,7 +1,83 @@ """asd""" -from homeassistant.components.scheduler import Event +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, description): - print('creating sun') +def create(schedule, event_listener_data): + 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) + + +class SunEventListener(ServiceEventListener): + 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): + 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._schedule.days: + next_time = next_time + timedelta(days=1) + + return next_time + + def schedule_next_event(self, hass, next_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 + + +class SunsetEventListener(SunEventListener): + def schedule(self, hass): + next_setting = sun.next_setting(hass) + + next_time = self.schedule_next_event(hass, next_setting) + + _LOGGER.info( + 'SunsetEventListener scheduled for {}, wiill call service {}.{}' + .format(next_time, self._domain, self._service)) + + +class SunriseEventListener(SunEventListener): + def schedule(self, hass): + next_rising = sun.next_rising(hass) + + next_time = self.schedule_next_event(hass, next_rising) + + _LOGGER.info( + 'SunriseEventListener scheduled for {}, wiill call service {}.{}' + .format(next_time, self._domain, self._service)) From b1cc760bd1f28159d75413972be21fcd5eb8ec20 Mon Sep 17 00:00:00 2001 From: Gustav Ahlberg Date: Sun, 28 Dec 2014 11:38:57 +0100 Subject: [PATCH 6/9] TimeEventListener uses ServiceEventListener --- homeassistant/components/scheduler/time.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/scheduler/time.py b/homeassistant/components/scheduler/time.py index ff4b1940eb0..e31661e5eb5 100644 --- a/homeassistant/components/scheduler/time.py +++ b/homeassistant/components/scheduler/time.py @@ -15,7 +15,7 @@ which time. from datetime import datetime, timedelta import logging -from homeassistant.components.scheduler import EventListener +from homeassistant.components.scheduler import ServiceEventListener from homeassistant.components import ATTR_ENTITY_ID _LOGGER = logging.getLogger(__name__) @@ -31,13 +31,11 @@ def create(schedule, event_listener_data): return TimeEventListener(schedule, service, hour, minute, second) -class TimeEventListener(EventListener): +class TimeEventListener(ServiceEventListener): """ The time event that the scheduler uses """ def __init__(self, schedule, service, hour, minute, second): - EventListener.__init__(self, schedule) - - (self._domain, self._service) = service.split('.') + ServiceEventListener.__init__(self, schedule, service) self._hour = hour self._minute = minute @@ -68,11 +66,3 @@ class TimeEventListener(EventListener): _LOGGER.info( 'TimeEventListener scheduled for {}, will call service {}.{}' .format(next_time, self._domain, self._service)) - - def execute(self, hass): - """ Call the service """ - data = {ATTR_ENTITY_ID: self._schedule.entity_ids} - hass.call_service(self._domain, self._service, data) - - # Reschedule for next day - self.schedule(hass) From 03e30ea5ed691675e6ad6fbdb2c6fe506fd221ed Mon Sep 17 00:00:00 2001 From: Gustav Ahlberg Date: Sun, 28 Dec 2014 14:56:50 +0100 Subject: [PATCH 7/9] SunEventListener documentation --- homeassistant/components/scheduler/sun.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/scheduler/sun.py b/homeassistant/components/scheduler/sun.py index fb76e607c43..92ef293910a 100644 --- a/homeassistant/components/scheduler/sun.py +++ b/homeassistant/components/scheduler/sun.py @@ -1,4 +1,17 @@ -"""asd""" +""" +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 b0b62d5db01079c5017913da387e03257fe01323 Mon Sep 17 00:00:00 2001 From: Gustav Ahlberg Date: Mon, 29 Dec 2014 00:59:22 +0100 Subject: [PATCH 8/9] Fixed some lint errors --- .../components/scheduler/__init__.py | 22 +++++----- homeassistant/components/scheduler/sun.py | 40 ++++++++++++++----- homeassistant/components/scheduler/time.py | 21 +++++----- 3 files changed, 53 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/scheduler/__init__.py b/homeassistant/components/scheduler/__init__.py index 451933fa4a4..c06f6acd7f5 100644 --- a/homeassistant/components/scheduler/__init__.py +++ b/homeassistant/components/scheduler/__init__.py @@ -17,11 +17,11 @@ entity_ids, and events. """ import logging import json -import importlib -from homeassistant.components import switch 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' @@ -69,6 +69,8 @@ def setup(hass, config): class Schedule(object): """ A Schedule """ + + # pylint: disable=too-many-arguments def __init__(self, schedule_id, name=None, description=None, entity_ids=None, days=None): @@ -80,22 +82,22 @@ class Schedule(object): self.days = days or [0, 1, 2, 3, 4, 5, 6] - self._event_listeners = [] + self.__event_listeners = [] def add_event_listener(self, event_listener): """ Add a event to the schedule """ - self._event_listeners.append(event_listener) + self.__event_listeners.append(event_listener) def schedule(self, hass): """ Schedule all the events in the schdule """ - for event in self._event_listeners: + for event in self.__event_listeners: event.schedule(hass) class EventListener(object): """ The base EventListner class that the schedule uses """ def __init__(self, schedule): - self._schedule = schedule + self.my_schedule = schedule def schedule(self, hass): """ Schedule the event """ @@ -105,18 +107,20 @@ class EventListener(object): """ execute the event """ pass + +# pylint: disable=too-few-public-methods class ServiceEventListener(EventListener): """ A EventListner that calls a service when executed """ def __init__(self, schdule, service): EventListener.__init__(self, schdule) - (self._domain, self._service) = service.split('.') + (self.domain, self.service) = service.split('.') def execute(self, hass): """ Call the service """ - data = {ATTR_ENTITY_ID: self._schedule.entity_ids} - hass.call_service(self._domain, self._service, data) + data = {ATTR_ENTITY_ID: self.my_schedule.entity_ids} + hass.call_service(self.domain, self.service, data) # Reschedule for next day self.schedule(hass) diff --git a/homeassistant/components/scheduler/sun.py b/homeassistant/components/scheduler/sun.py index 92ef293910a..cabe69063b2 100644 --- a/homeassistant/components/scheduler/sun.py +++ b/homeassistant/components/scheduler/sun.py @@ -23,12 +23,14 @@ _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('-')): + if offset_str.startswith('-'): negative_offset = True offset_str = offset_str[1:] @@ -42,26 +44,35 @@ def create(schedule, event_listener_data): 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 + self.offset = offset + self.negative_offset = negative_offset def __get_next_time(self, next_event): - if self._negative_offset: - next_time = next_event - self._offset + """ + 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 + next_time = next_event + self.offset while next_time < datetime.now() or \ - next_time.weekday() not in self._schedule.days: + 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 @@ -74,23 +85,30 @@ class SunEventListener(ServiceEventListener): 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 {}, wiill call service {}.{}' - .format(next_time, self._domain, self._service)) + 'SunsetEventListener scheduled for {}, will call service {}.{}' + .format(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 {}, wiill call service {}.{}' - .format(next_time, self._domain, self._service)) + 'SunriseEventListener scheduled for {}, will call service {}.{}' + .format(next_time, self.domain, self.service)) diff --git a/homeassistant/components/scheduler/time.py b/homeassistant/components/scheduler/time.py index e31661e5eb5..30f1ddf152f 100644 --- a/homeassistant/components/scheduler/time.py +++ b/homeassistant/components/scheduler/time.py @@ -16,7 +16,6 @@ from datetime import datetime, timedelta import logging from homeassistant.components.scheduler import ServiceEventListener -from homeassistant.components import ATTR_ENTITY_ID _LOGGER = logging.getLogger(__name__) @@ -26,33 +25,35 @@ def create(schedule, event_listener_data): service = event_listener_data['service'] (hour, minute, second) = [int(x) for x in - event_listener_data['time'].split(':')] + event_listener_data['time'].split(':')] return TimeEventListener(schedule, service, hour, minute, second) +# pylint: disable=too-few-public-methods class TimeEventListener(ServiceEventListener): """ The time event that the scheduler uses """ + # pylint: disable=too-many-arguments def __init__(self, schedule, service, hour, minute, second): ServiceEventListener.__init__(self, schedule, service) - self._hour = hour - self._minute = minute - self._second = second + self.hour = hour + self.minute = minute + self.second = second def schedule(self, hass): """ Schedule this event so that it will be called """ - next_time = datetime.now().replace(hour=self._hour, - minute=self._minute, - second=self._second, + next_time = datetime.now().replace(hour=self.hour, + minute=self.minute, + second=self.second, microsecond=0) # Calculate the next time the event should be executed. # That is the next day that the schedule is configured to run while next_time < datetime.now() or \ - next_time.weekday() not in self._schedule.days: + next_time.weekday() not in self.my_schedule.days: next_time = next_time + timedelta(days=1) @@ -65,4 +66,4 @@ class TimeEventListener(ServiceEventListener): _LOGGER.info( 'TimeEventListener scheduled for {}, will call service {}.{}' - .format(next_time, self._domain, self._service)) + .format(next_time, self.domain, self.service)) From 7066f25423ec74b2306e86a087568e089de92476 Mon Sep 17 00:00:00 2001 From: Gustav Ahlberg Date: Sun, 25 Jan 2015 21:50:54 +0100 Subject: [PATCH 9/9] Fixed logging-format-interpolation lint errors --- homeassistant/components/scheduler/sun.py | 8 ++++---- homeassistant/components/scheduler/time.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/scheduler/sun.py b/homeassistant/components/scheduler/sun.py index cabe69063b2..5af965a1764 100644 --- a/homeassistant/components/scheduler/sun.py +++ b/homeassistant/components/scheduler/sun.py @@ -95,8 +95,8 @@ class SunsetEventListener(SunEventListener): next_time = self.schedule_next_event(hass, next_setting) _LOGGER.info( - 'SunsetEventListener scheduled for {}, will call service {}.{}' - .format(next_time, self.domain, self.service)) + 'SunsetEventListener scheduled for %s, will call service %s.%s', + next_time, self.domain, self.service) # pylint: disable=too-few-public-methods @@ -110,5 +110,5 @@ class SunriseEventListener(SunEventListener): next_time = self.schedule_next_event(hass, next_rising) _LOGGER.info( - 'SunriseEventListener scheduled for {}, will call service {}.{}' - .format(next_time, self.domain, self.service)) + '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 30f1ddf152f..c1d8ebb7845 100644 --- a/homeassistant/components/scheduler/time.py +++ b/homeassistant/components/scheduler/time.py @@ -65,5 +65,5 @@ class TimeEventListener(ServiceEventListener): hass.track_point_in_time(execute, next_time) _LOGGER.info( - 'TimeEventListener scheduled for {}, will call service {}.{}' - .format(next_time, self.domain, self.service)) + 'TimeEventListener scheduled for %s, will call service %s.%s', + next_time, self.domain, self.service)