def new_history_entry(self, rain=0): """Create a new history entry""" values = {} n = now() for t, ml in self.meters.items(): sum_it = False sum_val = 0 sum_f = 0 for m in ml: f = m.weight v = m.get_value() if m.last_time is None: f *= 0.01 else: s = (n - m.last_time).total_seconds() if s > METER_MAXTIME: f *= 0.01 elif s > METER_TIME: f *= METER_TIME / s if v is not None: sum_val += f * v sum_f += f if m.sum_it: sum_it = True if sum_f: if not sum_it: sum_val /= sum_f values[t] = sum_val print("Values:", values, file=sys.stderr) h = History(site=self.s, time=now(), **values) h.save() return h
def new_history_entry(self,rain=0): """Create a new history entry""" values = {} n = now() for t,ml in self.meters.items(): sum_it = False sum_val = 0 sum_f = 0 for m in ml: f = m.weight v = m.get_value() if m.last_time is None: f *= 0.01 else: s = (n - m.last_time).total_seconds() if s > METER_MAXTIME: f *= 0.01 elif s > METER_TIME: f *= METER_TIME/s if v is not None: sum_val += f*v sum_f += f if m.sum_it: sum_it = True if sum_f: if not sum_it: sum_val /= sum_f values[t] = sum_val print("Values:",values, file=sys.stderr) h = History(site=self.s,time=now(),**values) h.save() return h
def has_rain(self): """Some monitor told us that it started raining""" r, self.rain_timer = self.rain_timer, gevent.spawn_later( self.s.db_rain_delay, connwrap, self.no_rain) if r: r.kill() return self.log("Started raining") self.rain = True #for v in self.s.valves.all(): vo = Valve.objects.filter(controller__site=self.s, runoff__gt=0) for v in vo.all(): valve = SchedValve(v) if valve.locked: continue try: valve._off(1) except NotConnected: pass except Exception: self.log_error(v) Schedule.objects.filter(valve__in=vo, start__gte=now() - timedelta(1), seen=False).delete() self.run_main_task()
def _on(self,sched=None,duration=None): print >>sys.stderr,"Open",self.v.var self.site.delay_on() if self.controller.has_max_on(): print >>sys.stderr,"… but too many:", " ".join(str(v) for v in self.controller.c.valves.all() if SchedValve(v).on) if sched: sched.update(seen = False) self.on = False self.log("NOT running for %s: too many"%(duration,)) raise TooManyOn(self) if duration is None and sched is not None: duration = sched.duration if duration is None: self.log("Run (indefinitely)") self.site.send_command("set","output","on",*(self.v.var.split())) else: self.log("Run for %s"%(duration,)) if not isinstance(duration,(int,long)): duration = duration.total_seconds() self.site.send_command("set","output","on",*(self.v.var.split()), sub=(("for",duration),("async",))) if sched is not None: if self.v.verbose: self.log("Opened for %s"%(sched,)) self.sched = sched if not sched.seen: sched.update(start=now(), seen = True) sched.refresh() #Save(sched) else: if self.v.verbose: self.log("Opened for %s"%(duration,))
def _range(self, start, end, forced=False, add=0): if start is None: start = now() r = [] if forced: # If this pass considers force-open times, only this matters r.append(self._forced_range(start, end)) else: # Apply groups' times r.append(self._group_range(start, end)) r.append(self._group_xrange(start, end)) # First step finished. r = [range_intersection(*r)] # Now add any group "allowed" one-shots. for g in self.groups.all(): r.append(g._allowed_range(start, end)) r = [range_union(*r)] # Now add any group "not-allowed" one-shots. for g in self.groups.all(): r.append(g._not_blocked_range(start, end)) # Also apply my own exclusion times r.append(self._not_blocked_range(start, end)) # Exclude times when this valve is already scheduled r.append(self._not_scheduled(start, end)) # Only consider times when the controller can open the valve and # there's enough water for it to run r.append(self.controller._range(start, end, add=add)) r.append(self.feed._range(start, end, self.flow, add=add)) return range_intersection(*r)
def _range(self,start,end, forced=False, add=0): if start is None: start = now() r = [] if forced: # If this pass considers force-open times, only this matters r.append(self._forced_range(start,end)) else: # Apply groups' times r.append(self._group_range(start,end)) r.append(self._group_xrange(start,end)) # First step finished. r = [range_intersection(*r)] # Now add any group "allowed" one-shots. for g in self.groups.all(): r.append(g._allowed_range(start,end)) r = [range_union(*r)] # Now add any group "not-allowed" one-shots. for g in self.groups.all(): r.append(g._not_blocked_range(start,end)) # Also apply my own exclusion times r.append(self._not_blocked_range(start,end)) # Exclude times when this valve is already scheduled r.append(self._not_scheduled(start,end)) # Only consider times when the controller can open the valve and # there's enough water for it to run r.append(self.controller._range(start,end,add=add)) r.append(self.feed._range(start,end,self.flow,add=add)) return range_intersection(*r)
def run_main_task(self, kill=True): """Run the calculation loop.""" res = None if not self._running.acquire(blocking=False): return self._run_result.get() try: self._run_result = AsyncResult() if kill: self._run.kill() n = now() ts = (n-self._run_last).total_seconds() if ts < 5: try: res = self.s.history.order_by("-time")[0] except IndexError: return None else: return res self._run_last = n res = self.main_task() return res finally: self._run = gevent.spawn_later((self._run_last+self._run_delay-n).total_seconds(), connwrap,self.run_main_task, kill=False) r,self._run_result = self._run_result,None self._running.release() r.set(res)
def run_main_task(self, kill=True): """Run the calculation loop.""" res = None if not self._running.acquire(blocking=False): return self._run_result.get() try: self._run_result = AsyncResult() if kill: self._run.kill() n = now() ts = (n - self._run_last).total_seconds() if ts < 5: try: res = self.s.history.order_by("-time")[0] except IndexError: return None else: return res self._run_last = n res = self.main_task() return res finally: self._run = gevent.spawn_later( (self._run_last + self._run_delay - n).total_seconds(), connwrap, self.run_main_task, kill=False) r, self._run_result = self._run_result, None self._running.release() r.set(res)
def stop(self): n=now() sec = (n-self.start).total_seconds() if sec > 3: self.res = sec else: self.feed.log("Flush broken: sec %s"%(sec,)) self._unlock()
def stop(self): n = now() sec = (n - self.start).total_seconds() if sec > 3: self.res = sec else: self.feed.log("Flush broken: sec %s" % (sec, )) self._unlock()
def monitor_value(self,event=None,**k): """monitor value NUMBER name…""" self.refresh() self.last_time = now() try: val = float(event[2]) self.add_value(val) except Exception: print_exc()
def add_flow(self,val): self.nflow += 1 if self.nflow == 2: self.start = now() if self.nflow > 2: self.flow += val if self.nflow == 9: self.stop() return False
def snapshot(self): n = now() if self.ts is not None and self.val is not None: w=(n-self.ts).total_seconds() if w > METER_TIME: w = METER_TIME # limit weight if the measurer dies self.avg += w*self.val self.nval += w self.ts = n
def snapshot(self): n = now() if self.ts is not None and self.val is not None: w = (n - self.ts).total_seconds() if w > METER_TIME: w = METER_TIME # limit weight if the measurer dies self.avg += w * self.val self.nval += w self.ts = n
def add_flow(self, val): self.nflow += 1 if self.nflow == 2: self.start = now() if self.nflow > 2: self.flow += val if self.nflow == 9: self.stop() return False
def current_history_entry(self, delta=15): # assure that the last history entry is reasonably current try: he = self.s.history.order_by("-time")[0] except IndexError: pass else: if (now() - he.time).total_seconds() < delta: return he return self.new_history_entry()
def current_history_entry(self,delta=15): # assure that the last history entry is reasonably current try: he = self.s.history.order_by("-time")[0] except IndexError: pass else: if (now()-he.time).total_seconds() < delta: return he return self.new_history_entry()
def stop(self): n = now() sec = (n - self.start).total_seconds() if sec > 3: self.res = self.flow / sec self.feed.d.update(flow=self.res) self.feed.d.refresh() else: self.feed.log("Flow check broken: sec %s" % (sec, )) self._unlock()
def stop(self): n=now() sec = (n-self.start).total_seconds() if sec > 3: self.res = self.flow/sec self.feed.d.update(flow = self.res) self.feed.d.refresh() else: self.feed.log("Flow check broken: sec %s"%(sec,)) self._unlock()
def monitor_value(self,value_delta=None,value=None,**kv): """monitor update name…""" self.refresh() self.last_time = now() try: if value_delta is not None: self.add_value(value_delta) else: self.add_value(value) except Exception: print_exc()
def monitor_value(self, value_delta=None, value=None, **kv): """monitor update name…""" self.refresh() self.last_time = now() try: if value_delta is not None: self.add_value(value_delta) else: self.add_value(value) except Exception: print_exc()
def new_level_entry(self, flow=0): self.site.current_history_entry() n = now() self.v.refresh() hts = None try: lv = self.v.levels.order_by("-time")[0] except IndexError: ts = n - timedelta(1, 0) else: ts = lv.time sum_f = 0 sum_r = 0 for h in self.site.s.history.filter(time__gt=ts).order_by("time"): if self.v.verbose > 2: self.log("Env factor for %s: T=%s W=%s S=%s" % (h, h.temp, h.wind, h.sun)) f = self.env.env_factor( h, logger=self.log if self.v.verbose > 2 else None) * self.v.adj if self.v.verbose > 1: self.log("Env factor for %s is %s" % (h, f)) sum_f += self.site.s.db_rate * self.v.do_shade( self.env.eg.factor * f) * (h.time - ts).total_seconds() sum_r += self.v.runoff * h.rain ts = h.time if self.v.verbose: self.log("Apply env %f, rain %r,, flow %f = %f" % (sum_f, sum_r, flow, flow / self.v.area)) if self.v.time == ts: return if self.v.level < 0: level = 0 else: level = F('level') level += sum_f if (flow > 0 or sum_r > 0) and self.v.level > self.v.max_level: level = self.v.max_level level -= flow / self.v.area + sum_r #if level < 0: # self.log("Level %s ?!?"%(self.v.level,)) self.v.update(time=ts, level=level) self.v.refresh() lv = Level(valve=self.v, time=ts, level=self.v.level, flow=flow) lv.save() if self.on and not (self.sched and self.sched.forced ) and self.v.level <= self.v.stop_level: self._off(5)
def _on(self, caller, sched=None, duration=None): print("Open", caller, self.v.var, file=sys.stderr) self.site.delay_on() if duration is None and sched is not None: duration = sched.duration if self.controller.has_max_on(): print("… but too many:", ", ".join( str(v) for v in self.controller.c.valves.all() if SchedValve(v).on), file=sys.stderr) if sched: sched.update(seen=False) self.log("NOT running %s for %s: too many" % ( self.v, duration, )) raise TooManyOn(self) if duration is None: self.log("Run (indefinitely)") self.site.send_command("set", "output", "on", *(self.v.var.split())) else: self.log("Run for %s" % (duration, )) if not isinstance(duration, six.integer_types): duration = duration.total_seconds() try: self.site.send_command("set", "output", "on", *(self.v.var.split()), sub=(("for", duration), ("async", ))) except Exception: # Something broke. Try to turn this thing off. self.log(format_exc()) self.site.send_command("set", "output", "off", *(self.v.var.split())) raise RuntimeError("Could not start (logged)") if sched is not None: if self.v.verbose: self.log("Opened for %s" % (sched, )) self.sched = sched if not sched.seen: sched.update(start=now(), seen=True) sched.refresh() #Save(sched) else: if self.v.verbose: self.log("Opened for %s" % (duration, ))
def sync_history(self): n=now() try: lv = self.v.levels.order_by("-time")[0] except IndexError: pass else: if self.v.time > lv.time: self.log("Timestamp downdate: %s %s" % (self.v.time,lv.time)) self.v.update(time = lv.time) self.v.refresh() #Save(self.v) if (n-self.v.time).total_seconds() > 3500: self.new_level_entry()
def sync_history(self): n = now() try: lv = self.v.levels.order_by("-time")[0] except IndexError: pass else: if self.v.time > lv.time: self.log("Timestamp downdate: %s %s" % (self.v.time, lv.time)) self.v.update(time=lv.time) self.v.refresh() #Save(self.v) if (n - self.v.time).total_seconds() >= 295: flow, self.flow = self.flow, 0 self.new_level_entry(flow)
def run_every(self,delay): """Initiate running the calculation and scheduling loop every @delay seconds.""" if self._run_delay is not None: self._run_delay = delay # just update return self._run_delay = delay self._run_last = now() self._running = Semaphore() self._run_result = None sd = self._run_delay.total_seconds()/10 if sd < 66: sd = 66 self._run = gevent.spawn_later(sd, connwrap,self.run_main_task, kill=False) if self._sched is not None: self._sched.kill() self._sched = gevent.spawn_later(2, connwrap,self.run_sched_task, kill=False, reason="run_every")
def new_level_entry(self,flow=0): self.site.current_history_entry() n=now() self.v.refresh() hts = None try: lv = self.v.levels.order_by("-time")[0] except IndexError: ts = n-timedelta(1,0) else: ts = lv.time sum_f = 0 sum_r = 0 for h in self.site.s.history.filter(time__gt=ts).order_by("time"): if self.v.verbose>2: self.log("Env factor for %s: T=%s W=%s S=%s"%(h,h.temp,h.wind,h.sun)) f = self.env.env_factor(h, logger=self.log if self.v.verbose>2 else None)*self.v.adj if self.v.verbose>1: self.log("Env factor for %s is %s"%(h,f)) sum_f += self.site.s.db_rate * self.v.do_shade(self.env.eg.factor*f) * (h.time-ts).total_seconds() sum_r += self.v.runoff*h.rain ts=h.time if self.v.verbose: self.log("Apply env %f, rain %r,, flow %f = %f" % (sum_f,sum_r,flow,flow/self.v.area)) if self.v.time == ts: return if self.v.level < 0: level = 0 else: level = F('level') level += sum_f if (flow > 0 or sum_r > 0) and self.v.level > self.v.max_level: level = self.v.max_level level -= flow/self.v.area+sum_r #if level < 0: # self.log("Level %s ?!?"%(self.v.level,)) self.v.update(time=ts, level=level) self.v.refresh() lv = Level(valve=self.v,time=ts,level=self.v.level,flow=flow) lv.save() if self.on and not (self.sched and self.sched.forced) and self.v.level <= self.v.stop_level: self._off(5)
def _on(self, caller, sched=None, duration=None): print("Open", caller, self.v.var, file=sys.stderr) self.site.delay_on() if duration is None and sched is not None: duration = sched.duration if self.controller.has_max_on(): print( "… but too many:", ", ".join(str(v) for v in self.controller.c.valves.all() if SchedValve(v).on), file=sys.stderr, ) if sched: sched.update(seen=False) self.log("NOT running %s for %s: too many" % (self.v, duration)) raise TooManyOn(self) if duration is None: self.log("Run (indefinitely)") self.site.send_command("set", "output", "on", *(self.v.var.split())) else: self.log("Run for %s" % (duration,)) if not isinstance(duration, six.integer_types): duration = duration.total_seconds() try: self.site.send_command( "set", "output", "on", *(self.v.var.split()), sub=(("for", duration), ("async",)) ) except Exception: # Something broke. Try to turn this thing off. self.log(format_exc()) self.site.send_command("set", "output", "off", *(self.v.var.split())) raise RuntimeError("Could not start (logged)") if sched is not None: if self.v.verbose: self.log("Opened for %s" % (sched,)) self.sched = sched if not sched.seen: sched.update(start=now(), seen=True) sched.refresh() # Save(sched) else: if self.v.verbose: self.log("Opened for %s" % (duration,))
def watch_state(self, value=None, **kv): """output change NAME ::value ON""" on = (str(value).lower() in ("1", "true", "on")) if self._flow_check is not None: # TODO self.on = on self._flow_check.state(on) return if self.locked: self.on = on return try: if on != self.on: n = now() print("Report %s" % ("ON" if on else "OFF"), self.v.var, self.sched, file=sys.stderr) if self.sched is not None and not on: self.sched.update( db_duration=(n - self.sched.start).total_seconds()) self.sched.refresh() self.sched_ts = self.sched.end self.sched = None flow, self.flow = self.flow, 0 # If nothing happened, calculate. if not on: duration = n - self.on_ts maxflow = self.v.flow * duration.total_seconds() if (not flow or not self.v.feed.var) or flow > 2 * maxflow: flow = maxflow self.new_level_entry(flow) if not on: if self.v.level > self.v.stop_level + ( self.v.start_level - self.v.stop_level) / 5: self.v.update(priority=True) self.log("Done for %s, level is now %s" % (duration, self.v.level)) self.on = on self.on_ts = n except Exception: print_exc()
def run_every(self, delay): """Initiate running the calculation and scheduling loop every @delay seconds.""" if self._run_delay is not None: self._run_delay = delay # just update return self._run_delay = delay self._run_last = now() self._running = Semaphore() self._run_result = None sd = self._run_delay.total_seconds() / 10 if sd < 66: sd = 66 self._run = gevent.spawn_later(sd, connwrap, self.run_main_task, kill=False) if self._sched is not None: self._sched.kill() self._sched = gevent.spawn_later(2, connwrap, self.run_sched_task, kill=False, reason="run_every")
def has_rain(self): """Some monitor told us that it started raining""" r,self.rain_timer = self.rain_timer,gevent.spawn_later(self.s.db_rain_delay,connwrap,self.no_rain) if r: r.kill() return self.log("Started raining") self.rain = True #for v in self.s.valves.all(): vo = Valve.objects.filter(controller__site=self.s, runoff__gt=0) for v in vo.all(): valve = SchedValve(v) if valve.locked: continue try: valve._off(1) except NotConnected: pass except Exception: self.log_error(v) Schedule.objects.filter(valve__in=vo, start__gte=now()-timedelta(1),seen=False).delete() self.run_main_task()
def watch_state(self,value=None,**kv): """output change NAME ::value ON""" on = (str(value).lower() in ("1","true","on")) if self._flow_check is not None: # TODO self.on = on self._flow_check.state(on) return if self.locked: self.on = on return try: if on != self.on: n=now() print("Report %s" % ("ON" if on else "OFF"),self.v.var,self.sched, file=sys.stderr) if self.sched is not None and not on: self.sched.update(db_duration=(n-self.sched.start).total_seconds()) self.sched.refresh() self.sched_ts = self.sched.end self.sched = None flow,self.flow = self.flow,0 # If nothing happened, calculate. if not on: duration = n-self.on_ts maxflow = self.v.flow * duration.total_seconds() if (not flow or not self.v.feed.var) or flow > 2*maxflow: flow = maxflow self.new_level_entry(flow) if not on: if self.v.level > self.v.stop_level + (self.v.start_level-self.v.stop_level)/5: self.v.update(priority=True) self.log("Done for %s, level is now %s"%(duration,self.v.level)) self.on = on self.on_ts = n except Exception: print_exc()
def queryset(self, request): qs = super(LevelInline, self).queryset(request) return qs.filter(time__gte = now()-timedelta(1,0)).order_by("-time")
def list_range(self): if self.days.count()+self.xdays.count()+self.overrides.filter(start__gt=now()).count() == 0: return u"‹no dates›" return super(Group,self).list_range()
def save(self,commit=True): if self.instance.id is None: self.instance.time = now() self.instance.valve = self.aux_data['valve'] self.instance.forced = True return super(LevelForm,self).save(commit)
def _run_schedule(self): if self.sched_job is not None: self.sched_job.kill() self.sched_job = None if self.locked: if self.v.verbose: print("SCHED LOCKED2 %s" % (self.v.name,), file=sys.stderr) return n = now() try: if self.sched is not None: self.sched.refresh() if self.sched.end <= n: if self.v.verbose: print("Turn off: %s+%s <= %s" % (self.sched.start,self.sched.duration,n), file=sys.stderr) self._off(2) self.sched = None else: self.sched_job = gevent.spawn_later((self.sched.end-n).total_seconds(),connwrap,self.run_sched_task,reason="_run_schedule 1") if self.v.verbose: print("SCHED LATER %s: %s" % (self.v.name,humandelta(self.sched.end-n)), file=sys.stderr) return except ObjectDoesNotExist: pass # somebody deleted it *shrug* sched = None if self.sched_ts is None: try: sched = self.v.schedules.filter(start__lt=n).order_by("-start")[0] except IndexError: self.sched_ts = n-timedelta(1,0) else: self.sched_ts = sched.end if sched.end > n: # still running if self.v.verbose: print("SCHED RUNNING %s: %s" % (self.v.name,humandelta(sched.end-n)), file=sys.stderr) try: self._on(1,sched, sched.end-n) except TooManyOn: self.log("Could not schedule: too many open valves") except NotConnected: self.log("Could not schedule: connection to MoaT failed") return try: sched = self.v.schedules.filter(start__gte=self.sched_ts).order_by("start")[0] except IndexError: if self.v.verbose: print("SCHED EMPTY %s: %s" % (self.v.name,str_tz(self.sched_ts)), file=sys.stderr) self._off(3) return if sched.end <= n: if self.v.verbose: print("SCHED %s: sched %d done for %s" % (self.v.name,sched.id,humandelta(n-sched.end)), file=sys.stderr) self.sched_ts = None return if sched.start > n: if self.v.verbose: print("SCHED %s: sched %d in %s" % (self.v.name,sched.id,humandelta(sched.start-n)), file=sys.stderr) self._off(4) self.sched_job = gevent.spawn_later((sched.start-n).total_seconds(),connwrap,self.run_sched_task,reason="_run_schedule 2") return try: self._on(2,sched) except TooManyOn: self.log("Could not schedule: too many open valves") except NotConnected: self.log("Could not schedule: connection to MoaT failed")
def get_queryset(self, request): qs = super(ScheduleInline, self).queryset(request) return qs.filter(start__gte = now()-timedelta(0.5)).order_by("start")
def get_queryset(self, request): qs = super(LevelInline, self).queryset(request) return qs.filter(time__gte = now()-timedelta(1,0)).order_by("-time")
def get_queryset(self, request): qs = super(ValveOverrideInline, self).queryset(request) return qs.filter(start__gte = now()-timedelta(1,0)).order_by("-start")
def save(self, commit=True): if self.instance.id is None: self.instance.time = now() self.instance.valve = self.aux_data['valve'] self.instance.forced = True return super(LevelForm, self).save(commit)
def queryset(self, request): qs = super(ValveOverrideInline, self).queryset(request) return qs.filter(start__gte = now()-timedelta(1,0)).order_by("-start")
from django.core.management.base import BaseCommand, CommandError from rainman.models import Site,Valve,Schedule,Controller,History,Level from rainman.utils import now,str_tz from rainman.logging import log from datetime import datetime,time,timedelta from django.db.models import F,Q from django.utils.timezone import utc,get_current_timezone from optparse import make_option from time import sleep from traceback import print_exc import rpyc import errno import sys n=now() soon=n+timedelta(0,15*60) later=n+timedelta(0,2*60*60) class Command(BaseCommand): args = '<valve>…' help = 'Generate a schedule' option_list = BaseCommand.option_list + ( make_option('-s','--site', action='store', dest='site', default=None, help='Select the site to use'), make_option('-c','--controller', action='store',
def _run_schedule(self): if self.sched_job is not None: self.sched_job.kill() self.sched_job = None if self.locked: if self.v.verbose: print("SCHED LOCKED2 %s" % (self.v.name, ), file=sys.stderr) return n = now() try: if self.sched is not None: self.sched.refresh() if self.sched.end <= n: if self.v.verbose: print("Turn off: %s+%s <= %s" % (self.sched.start, self.sched.duration, n), file=sys.stderr) self._off(2) self.sched = None else: self.sched_job = gevent.spawn_later( (self.sched.end - n).total_seconds(), connwrap, self.run_sched_task, reason="_run_schedule 1") if self.v.verbose: print("SCHED LATER %s: %s" % (self.v.name, humandelta(self.sched.end - n)), file=sys.stderr) return except ObjectDoesNotExist: pass # somebody deleted it *shrug* sched = None if self.sched_ts is None: try: sched = self.v.schedules.filter( start__lt=n).order_by("-start")[0] except IndexError: self.sched_ts = n - timedelta(1, 0) else: self.sched_ts = sched.end if sched.end > n: # still running if self.v.verbose: print("SCHED RUNNING %s: %s" % (self.v.name, humandelta(sched.end - n)), file=sys.stderr) try: self._on(1, sched, sched.end - n) except TooManyOn: self.log("Could not schedule: too many open valves") except NotConnected: self.log( "Could not schedule: connection to MoaT failed") return try: sched = self.v.schedules.filter( start__gte=self.sched_ts).order_by("start")[0] except IndexError: if self.v.verbose: print("SCHED EMPTY %s: %s" % (self.v.name, str_tz(self.sched_ts)), file=sys.stderr) self._off(3) return if sched.end <= n: if self.v.verbose: print("SCHED %s: sched %d done for %s" % (self.v.name, sched.id, humandelta(n - sched.end)), file=sys.stderr) self.sched_ts = None return if sched.start > n: if self.v.verbose: print("SCHED %s: sched %d in %s" % (self.v.name, sched.id, humandelta(sched.start - n)), file=sys.stderr) self._off(4) self.sched_job = gevent.spawn_later( (sched.start - n).total_seconds(), connwrap, self.run_sched_task, reason="_run_schedule 2") return try: self._on(2, sched) except TooManyOn: self.log("Could not schedule: too many open valves") except NotConnected: self.log("Could not schedule: connection to MoaT failed")
def queryset(self, request): qs = super(ScheduleInline, self).queryset(request) return qs.filter(start__gte = now()-timedelta(0.5)).order_by("start")
from django.core.management.base import BaseCommand, CommandError from rainman.models import Site,Valve,Schedule,Controller,History,Level from rainman.utils import now,str_tz from rainman.logging import log from datetime import datetime,time,timedelta from django.db.models import F,Q from django.utils.timezone import utc,get_current_timezone from optparse import make_option from time import sleep from traceback import print_exc import rpyc import errno import sys n=now() soon=n+timedelta(0,15*60) later=n+timedelta(0,2*60*60) class Command(BaseCommand): args = '<valve>…' help = 'Generate a schedule' def add_arguments(self, parser): parser.add_argument('-s','--site', action='store', dest='site', default=None, help='Select the site to use') parser.add_argument('-c','--controller', action='store',