class Program(object): def __init__(self, p, s, t, callback): self._p = p self._s = s self._t = t self._r = None self._callback = callback self._step_cnt = 0 self._step = -1 self._step_time = 0 self._run_time = 0 self._running = False self._timer = None def start(self): module_logger.debug("start()") self._step_cnt = len(self._p["steps"]) self._running = True self.run_step() def cancel(self): module_logger.debug("cancel()") self._running = False if self._r is not None: self._r.force_off() def stop(self): module_logger.debug("stop()") self._running = False self._r = None self._step = -1 self._step_cnt = 0 if self._callback is not None: self._callback() def run_step(self): self._step += 1 self._step_time = 0 self._run_time = 0 if self._timer is not None: self._timer.cancel() if not self._running or self._step >= self._step_cnt: self.stop() else: log_msg = f"run_step() [{self._step + 1} of {self._step_cnt}]" run = True for step in self._p['steps']: if step['step'] == self._step: head = -1 pin = 0 zone = step['zone'] for z in self._s['zones']: if z['zone'] == zone: pin = z['pin'] head = z['type'] break if pin > 0 and head >= 0: self._r = Relay(pin, self.run_step) if step['time'] > 0: t = step['time'] * 60 else: t = self.det_run_time(step['percent'] / 100.0, head) t = t * 12.0 / (28.0 / self._p['interval']) log_msg += f" zone[{zone}] head[{head}] pin[{pin}] time[{int(t/60)}]" if t > 0: run = False self._step_time = int(t) self._r.set_run_time(int(t)) w = 3 if step['wait'] > 0: w = step['wait'] * 60 self._r.set_wait(w) self._r.on() self._timer = threading.Timer( 60, self.set_run_time) self._timer.start() else: run = True module_logger.debug(log_msg) if run: self.run_step() def set_run_time(self): if self._running: self._run_time += 1 self._timer = threading.Timer(60, self.set_run_time) self._timer.start() def det_run_time(self, p, h): date = dt.datetime.today() month = dt.date.today().month - 1 date = date.replace(hour=0, minute=0, second=0, microsecond=0) date -= dt.timedelta(days=1) act_temp = 0 act_cnt = 0 for day in self._t["history"]: if day["dt"] == str(date.date()): act_temp += day["tAvg"] act_cnt += 1.0 break date -= dt.timedelta(days=1) for day in self._t["history"]: if day["dt"] == str(date.date()): act_temp += day["tAvg"] act_cnt += 1.0 break if act_cnt == 0: module_logger.debug("det_run_time() temp history not found.") return 0 else: avg_temp = act_temp / act_cnt per_temp = 1.0 if self._s['average_temps'][month] > 0: per_temp = get_f_from_c(avg_temp) / self._s['average_temps'][month] return self._s['watering_times'][h][month] * per_temp * 60.0 * p @property def p(self): return self._p @property def step(self): return self._step @property def step_cnt(self): return self._step_cnt @property def step_time(self): return self._step_time @property def run_time(self): return self._run_time @property def running(self): return self._running