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)