diff --git a/scheduler.py b/scheduler.py new file mode 100644 --- /dev/null +++ b/scheduler.py @@ -0,0 +1,81 @@ +from apscheduler.schedulers.background import BackgroundScheduler +from pytz import timezone +import ast +import datetime +import logging + +class Scheduler: + + def __init__(self, network, config): + self.logger = logging.getLogger('hydrobot') + self.network = network + self.config = config + + self.apscheduler = BackgroundScheduler() + self.apscheduler.configure(timezone=timezone(config.get("system", "timezone"))) + + def start(self): + self.apscheduler.start() + self.load_schedules() + + def interval_on(self, module, output, timer_off, timer_on, on_duration): + module.set_output(output, 1) + self.apscheduler.get_job(timer_on).reschedule("interval", weeks = on_duration[0], days = on_duration[1], hours = on_duration[2], minutes = on_duration[3], seconds = on_duration[4]) + self.apscheduler.get_job(timer_on).resume() + self.apscheduler.get_job(timer_off).pause() + self.logger.info("Turning " + timer_on + "!") + + def interval_off(self, module, output, timer_off, timer_on, off_duration): + module.set_output(output, 0) + self.apscheduler.get_job(timer_off).reschedule("interval", weeks = off_duration[0], days = off_duration[1], hours = off_duration[2], minutes = off_duration[3], seconds = off_duration[4]) + self.apscheduler.get_job(timer_off).resume() + self.apscheduler.get_job(timer_on).pause() + self.logger.info("Turning " + timer_off + "!") + + def add_schedule(self, name, trigger, module_name, output, on_param, off_param): + + module = self.network.module_list.lookup_module_by_name(module_name) + if not module == None: + + if trigger == "cron": + on_job = self.apscheduler.add_job(module.set_output, trigger, [output, 1], day = on_param[0], day_of_week = on_param[1], hour = on_param[2], minute = on_param[3], second = on_param[4]) + off_job = self.apscheduler.add_job(module.set_output, trigger, [output, 0], day = off_param[0], day_of_week = off_param[1], hour = off_param[2], minute = off_param[3], second = off_param[4]) + + #evalute the current state of the cron trigger and set output on if needed + if on_job.next_run_time > off_job.next_run_time: + module.set_output(output, 1) + else: + module.set_output(output, 0) + + if trigger == "interval": + self.apscheduler.add_job(self.interval_on, trigger, [module, output, name + "_off", name + "_on", on_param], id = name + "_off", weeks = off_param[0], days = off_param[1], hours = off_param[2], minutes = off_param[3], seconds = off_param[4]) + timer = self.apscheduler.add_job(self.interval_off, trigger, [module, output, name + "_off", name + "_on", off_param], id = name + "_on", weeks = on_param[0], days = on_param[1], hours = on_param[2], minutes = on_param[3], seconds = on_param[4]) + timer.pause() + self.interval_on(module, output, name + "_off", name + "_on", on_param) + + else: + self.logger.warning("Module not found: " + module_name) + + + def load_schedules(self): + + for section in self.config.sections(): + if "timer" in section: + items = self.config.items(section) + for item in items: + if item[0] == "trigger": + trigger = item[1] + if item[0] == "module_name": + module_name = item[1] + if item[0] == "output": + output = item[1] + if item[0] == "on_time": + on_param = ast.literal_eval(item[1]) + if item[0] == "off_time": + off_param = ast.literal_eval(item[1]) + if item[0] == "on_duration": + on_param = ast.literal_eval(item[1]) + if item[0] == "off_duration": + off_param = ast.literal_eval(item[1]) + + self.add_schedule(section, trigger, module_name, output, on_param, off_param)