def dataReceived(self, data): self._stop_timer() data = self.dbuf + data while True: xi = len(data) + 1 try: pi = data.index(b'\r') except ValueError: pi = xi try: ei = data.index(b'\n') except ValueError: ei = xi if pi == xi and ei == xi: break if pi < ei: self.lbuf = data[:pi].decode('utf-8') data = data[pi + 1:] else: msg = data[:ei].decode('utf-8') data = data[ei + 1:] if msg == "" and self.lbuf is not None: msg = self.lbuf self.lbuf = None try: self.lineReceived(msg) except Exception as e: log("fs20", ERROR, msg, e) fix_exception(e) process_failure(e) self.dbuf = data self._start_timer()
def run(self,ctx,**k): event = self.params(ctx) try: out = self.ctx.out except AttributeError: out = sys.stderr if not len(event): for s,v in LogNames.items(): print("%d = %s" % (s,v), file=out) print(".", file=out) return None if len(event) > 1: log(getattr(logging,event[0].upper()), *event[1:]) else: level = getattr(logging,event[0].upper()) if level == logging.NONE: if hasattr(out,"logger"): out.logger.delete() del out.logger else: if hasattr(out,"logger"): out.logger.level = level else: try: out = self.ctx.out except AttributeError: out = sys.stderr logger = OutLogger(out=out, level=level) try: out.logger = logger except AttributeError: pass # file objects don't except: logger.delete() raise
def get_collect(name, allow_collection=False): c = None if not len(name): return None coll = collections if allow_collection and name[-1] == "*": return coll[Name(*name[:-1])] while len(name): n = len(name) while n > 0: try: coll = coll[Name(*name[:n])] except KeyError: n = n-1 else: name = name[n:] if c is None: c = coll break if n == 0: try: coll = coll[name[0]] except KeyError: from moat.logging import DEBUG,log log(DEBUG,"Contents: "+", ".join(str(x) for x in coll.keys())) raise CKeyError(name,coll) else: name = name[1:] if c is None: c = coll if not allow_collection and not isinstance(coll,Collected): raise CCollError(name) return coll
def up(self): dev = devices[self.device] if self.switch is not None and self.switched is None: log(DEBUG,"switch low1",self.switch,self.to_low) dev.set(self.switch,self.to_low) self.switched = False return super(OWFSmon,self).up()
def get_collect(name, allow_collection=False): c = None if not len(name): return None coll = collections if allow_collection and name[-1] == "*": return coll[Name(*name[:-1])] while len(name): n = len(name) while n > 0: try: coll = coll[Name(*name[:n])] except KeyError: n = n - 1 else: name = name[n:] if c is None: c = coll break if n == 0: try: coll = coll[name[0]] except KeyError: from moat.logging import DEBUG, log log(DEBUG, "Contents: " + ", ".join(str(x) for x in coll.keys())) raise CKeyError(name, coll) else: name = name[1:] if c is None: c = coll if not allow_collection and not isinstance(coll, Collected): raise CCollError(name) return coll
def _do_measure(self): log("monitor",TRACE,"Start run",self.name) try: self.running.clear() self.started_at = now() self._monitor() if self.send_check_event: simple_event(self.ectx, "monitor","checked",*self.name) if self.new_value is not None: self.last_value = self.value self.value = self.new_value if hasattr(self,"delta"): if self.last_value is not None: val = self.value-self.last_value self._ectx.value_delta = val if val >= 0 or self.delta == 0: simple_event(self.ectx,"monitor","update",*self.name) else: simple_event(self.ectx,"monitor","update",*self.name) except Exception as e: fix_exception(e) process_failure(e) finally: log("monitor",TRACE,"Stop run",self.name) self.running.set() self._schedule()
def got_entry(name): if key is None and name.startswith("bus."): buses.append(name) elif len(name)>3 and name[2] == ".": entries.append(name) else: log("onewire",TRACE,"got unrecognized name %s" % (name,))
def up(self): dev = devices[self.device] if self.switch is not None and self.switched is None: log(DEBUG, "switch low1", self.switch, self.to_low) dev.set(self.switch, self.to_low) self.switched = False return super(OWFSmon, self).up()
def lineReceived(self, data): db = "" e = "" if not data: return # empty line if data[0] in PREFIX: for d in data[1:]: if e: try: db += chr(eval("0x" + e + d)) except SyntaxError: simple_event("fs20", "unknown", "hex", data=data) return e = "" else: e = d if e: log("fs20", WARN, "fs20 odd length " + data) self.datagramReceived(data[0], db, timestamp=self.timestamp) self.timestamp = None elif data[0] == PREFIX_TIMESTAMP: self.timestamp = float(data[1:]) elif data[0] == "P": pass # idle elif data[0] == "+": log("fs20", DEBUG, "fs20 trace " + data) else: simple_event("fs20", "unknown", "prefix", prefix=data[0], data=data[1:])
def error(self, err): """An error occurred.""" if self.result is not None and not self.result.successful: log("onewire", DEBUG, "done error: ", self, err) self.result.set_exception(err) else: process_failure(err)
def start_up(self): f = connect(name=self.dest, host=self.host, port=self.port, scan=self.scan) buses[self.dest] = f log(TRACE, "New OWFS bus", self.dest, f)
def lineReceived(self,data): db = "" e = "" if not data: return # empty line if data[0] in PREFIX: for d in data[1:]: if e: try: db += chr(eval("0x"+e+d)) except SyntaxError: simple_event("fs20","unknown","hex", data=data) return e="" else: e=d if e: log("fs20",WARN,"fs20 odd length "+data) self.datagramReceived(data[0], db, timestamp=self.timestamp) self.timestamp = None elif data[0] == PREFIX_TIMESTAMP: self.timestamp = float(data[1:]) elif data[0] == "P": pass # idle elif data[0] == "+": log("fs20",DEBUG,"fs20 trace "+data) else: simple_event("fs20","unknown","prefix", prefix=data[0],data=data[1:])
def error(self,err): """An error occurred.""" if self.result is not None and not self.result.successful: log("onewire",DEBUG,"done error: ",self,err) self.result.set_exception(err) else: process_failure(err)
def dataReceived(self, data): self._stop_timer() data = self.dbuf+data while True: xi = len(data)+1 try: pi = data.index(b'\r') except ValueError: pi = xi try: ei = data.index(b'\n') except ValueError: ei = xi if pi==xi and ei==xi: break if pi < ei: self.lbuf = data[:pi].decode('utf-8') data = data[pi+1:] else: msg = data[:ei].decode('utf-8') data = data[ei+1:] if msg == "" and self.lbuf is not None: msg = self.lbuf self.lbuf = None try: self.lineReceived(msg) except Exception as e: log("fs20",ERROR,msg,e) fix_exception(e) process_failure(e) self.dbuf = data self._start_timer()
def got_entry(name): if key is None and name.startswith("bus."): buses.append(name) elif len(name) > 3 and name[2] == ".": entries.append(name) else: log("onewire", TRACE, "got unrecognized name %s" % (name, ))
def exposed_write(self,s): i = s.find("\n") while i >= 0: log("TEST",DEBUG,">>>",self.buf+s[:i]) self.buf = "" s = s[i+1:] i = s.find("\n") self.buf += s
def _init(self, bus, short_id=None, id=None, path=()): log("onewire",DEBUG,"NEW", bus,short_id,id,path) self.bus_id = id if short_id: self.id = short_id.lower() self.bus = bus assert path is not None self.path = path self.is_up = None self.ctx = Context()
def error(self, err): log("wago", DEBUG, "Got error", self, err) simple_event("output", "error", *self.queue.name, value=self.val, error=err) if not self.result.ready(): self.result.set(err) super(WAGOtimedOutputRun, self).error(err)
def _init(self, bus, short_id=None, id=None, path=()): log("onewire", DEBUG, "NEW", bus, short_id, id, path) self.bus_id = id if short_id: self.id = short_id.lower() self.bus = bus assert path is not None self.path = path self.is_up = None self.ctx = Context()
def do_post(self): self.slotter = None if self.running != "during" or self.waiter is not None: log(ERROR,"timeslot error post",self.running,*self.name) return self.running = "next" simple_event("timeslot","end",*self.name, deprecated=True) simple_event("timeslot","state",*self.name, state="end") self.next = time_delta(self.interval, now=self.next)-dt.timedelta(0,self.duration) self.waiter = callLater(False, self.next, self.do_pre)
def _update_all(self): log("onewire",TRACE,"start bus update") old_ids = devices.copy() new_ids = {} seen_ids = {} old_bus = set(self.bus_paths.keys()) new_bus = set() def bus_cb(path): if path in old_bus: old_bus.remove(path) else: new_bus.add(path) for dev in self.all_devices(bus_cb): if dev.id in seen_ids: continue seen_ids[dev.id] = dev if dev.id in old_ids: del old_ids[dev.id] else: new_ids[dev.id] = dev n_old = 0 n_dev = 0 for dev in old_ids.values(): if dev.bus is self: n_old += 1 ## Just because something vanishes from the listing ## doesn't mean it's dead; the bus may be a bit unstable # dev.go_down() log("onewire",DEBUG,"Bus unstable?",self.name,dev.id) for dev in devices.values(): if dev.bus is self: n_dev += 1 for dev in old_bus: bp = self.bus_paths.pop(dev) bp.stop() simple_event("onewire","bus","down", bus=self.name,path=dev) simple_event("onewire","bus","state",self.name,"/".join(dev), bus=self.name,path=dev, state="down") for dev in new_bus: self.bus_paths[dev] = OWFSbuspath(self,dev) simple_event("onewire","bus","up", bus=self.name,path=dev) simple_event("onewire","bus","state",self.name,"/".join(dev), bus=self.name,path=dev, state="up") # success only, error above simple_event("onewire","scanned",*self.name, old=n_old, new=len(new_ids), num=n_dev, deprecated=True) simple_event("onewire","scan",*self.name, run="done", old=n_old, new=len(new_ids), num=n_dev)
def lineReceived(self, line): log("wago", TRACE, "recv", repr(line)) msgid = 0 off = 0 mt = MT_OTHER if self.buf is not None: if line == ".": buf, self.buf = self.buf, None self.msgReceived(type=MT_MULTILINE, msg=buf) else: if line.startswith("."): line = line[1:] self.buf.append(line) return elif line == "": self.msgReceived(type=MT_OTHER, msg=line) elif line[0] == "=": self.buf = [line[1:]] return elif line[0] == "?": self.msgReceived(type=MT_ERROR, msg=line[1:].strip()) return elif line[0] == "*": self.msgReceived(type=MT_INFO, msg=line[1:].strip()) return elif line[0] == "+": self.msgReceived(type=MT_ACK, msg=line[1:].strip()) return elif line[0] == "-": self.msgReceived(type=MT_NAK, msg=line[1:].strip()) return elif line[0] == "!": if line[1] == "+": mt = MT_IND_ACK off = 2 elif line[1] == "-": mt = MT_IND_NAK off = 2 else: mt = MT_IND off = 1 while off < len(line) and line[off].isdigit(): msgid = 10 * msgid + int(line[off]) off += 1 if msgid > 0: self.msgReceived(type=mt, msgid=msgid, msg=line[off:].strip()) else: self.msgReceived(type=mt, msg=line.strip())
def lineReceived(self, line): log("wago",TRACE,"recv",repr(line)) msgid = 0 off = 0 mt = MT_OTHER if self.buf is not None: if line == ".": buf,self.buf = self.buf,None self.msgReceived(type=MT_MULTILINE, msg=buf) else: if line.startswith("."): line = line[1:] self.buf.append(line) return elif line == "": self.msgReceived(type=MT_OTHER, msg=line) elif line[0] == "=": self.buf = [line[1:]] return elif line[0] == "?": self.msgReceived(type=MT_ERROR, msg=line[1:].strip()) return elif line[0] == "*": self.msgReceived(type=MT_INFO, msg=line[1:].strip()) return elif line[0] == "+": self.msgReceived(type=MT_ACK, msg=line[1:].strip()) return elif line[0] == "-": self.msgReceived(type=MT_NAK, msg=line[1:].strip()) return elif line[0] == "!": if line[1] == "+": mt = MT_IND_ACK off = 2 elif line[1] == "-": mt = MT_IND_NAK off = 2 else: mt = MT_IND off = 1 while off < len(line) and line[off].isdigit(): msgid = 10*msgid+int(line[off]) off += 1 if msgid > 0: self.msgReceived(type=mt, msgid=msgid, msg=line[off:].strip()) else: self.msgReceived(type=mt, msg=line.strip())
def cont(self, _=None): while self.waiting: try: msg = self.waiting.pop(0) log("fs20", DEBUG, msg) d = self._dataReceived(msg) except Exception as e: fix_exception(e) process_failure(e) else: if d: d.addCallback(self.cont) return self.waiting = None self._start_timer()
def cont(self, _=None): while self.waiting: try: msg = self.waiting.pop(0) log("fs20",DEBUG,msg) d = self._dataReceived(msg) except Exception as e: fix_exception(e) process_failure(e) else: if d: d.addCallback(self.cont) return self.waiting = None self._start_timer()
def do_pre(self): self.waiter = None if self.running != "next" or self.slotter is not None: log(ERROR,"timeslot error pre",self.running,*self.name) return if self.next is None: self.next = now() self.last = self.next self.running = "during" simple_event("timeslot","begin",*self.name, deprecated=True) simple_event("timeslot","state",*self.name, state="begin") self.next += dt.timedelta(0,self.duration) self.slotter = callLater(False,self.next, self.do_post)
def sendMsg(self, typ, data, rlen): """Send an OWFS message to the other end of the connection. """ flags = 0 if self.persist: flags |= OWFlag.persist # needed for sometimes-broken 1wire daemons flags |= OWFlag.busret # flags |= 1<<8 ## ? flags |= OWtempformat.celsius << OWtempformat._offset flags |= OWdevformat.fdi << OWdevformat._offset log("onewire",DEBUG,"SEND", 0, len(data), typ, flags, rlen, 0, repr(data)) self.write(struct.pack("!6i", \ 0, len(data), typ, flags, rlen, 0) +data)
def called(env,*a,**k): log(TRACE,"PY Proc called",env,a,k) env.on("test","me", doc="Test me harder",name="foo test bar")(running) env.on("test","me","not", doc="dummy")(not_running) if env.test.true(): env.do.log.DEBUG("true") if env.test('false'): env.do.log.ERROR("false") env.trigger("test","it", what="ever") env.do.wait("some delay",_for="0.2 min") env.do.wait("more","delay",_for=(0.3,"min")) for k in env.data['on']: env.do.log.DEBUG("Handler",k) env.do("log DEBUG 'do' works") env.do.log('DEBUG', "'do.log' works") log(TRACE,"PY Proc done")
def called(env, *a, **k): log(TRACE, "PY Proc called", env, a, k) env.on("test", "me", doc="Test me harder", name="foo test bar")(running) env.on("test", "me", "not", doc="dummy")(not_running) if env.test.true(): env.do.log.DEBUG("true") if env.test('false'): env.do.log.ERROR("false") env.trigger("test", "it", what="ever") env.do.wait("some delay", _for="0.2 min") env.do.wait("more", "delay", _for=(0.3, "min")) for k in env.data['on']: env.do.log.DEBUG("Handler", k) env.do("log DEBUG 'do' works") env.do.log('DEBUG', "'do.log' works") log(TRACE, "PY Proc done")
def sendMsg(self, typ, data, rlen): """Send an OWFS message to the other end of the connection. """ flags = 0 if self.persist: flags |= OWFlag.persist # needed for sometimes-broken 1wire daemons flags |= OWFlag.busret # flags |= 1<<8 ## ? flags |= OWtempformat.celsius << OWtempformat._offset flags |= OWdevformat.fdi << OWdevformat._offset log("onewire", DEBUG, "SEND", 0, len(data), typ, flags, rlen, 0, repr(data)) self.write(struct.pack("!6i", \ 0, len(data), typ, flags, rlen, 0) +data)
def __init__(self, parent, args, name=None, prio=(MIN_PRIO+MAX_PRIO)//2+1): self.prio = prio self.displayname = name self.args = args self.parent = parent if name is None: name = Name("_on",self._get_id()) super(OnEventBase,self).__init__(*name) for k in self.args: if hasattr(k,'startswith') and k.startswith('*'): self._simple = False # self.name = six.text_type(self.args) # if self.displayname is not None: # self.name += u" ‹"+" ".join(six.text_type(x) for x in self.displayname)+u"›" log(TRACE,"NewHandler",self.id)
def recv(self, msg): if msg.type is MT_MULTILINE: for x in msg.msg: if x == "": continue m = _num.match(x) if m is None: continue mon = int(m.group(0)) self.data[mon] = x[m.end():] recvs, self.queue.receivers = self.queue.receivers, [] for r in recvs: mid = getattr(r, "msgid", None) if mid is None or mid in self.data: log("wago", TRACE, "found monitor", r) self.queue.receivers.append(r) else: try: raise DroppedMonitor(mid) except DroppedMonitor as ex: fix_exception(ex) res = r.error(ex) if res is SEND_AGAIN: log("wago", TRACE, "retry monitor", r) self.queue.enqueue(r) else: log("wago", TRACE, "drop monitor", r) assert res is None or res is False, "%s.error returned %s" % ( repr(r), repr(res)) return MINE if msg.type is MT_NAK or msg.type is MT_ERROR: simple_event("wago", "monitor", "error", msg=msg.msg) return MINE return NOT_MINE
def recv(self,msg): if msg.type is MT_MULTILINE: for x in msg.msg: if x == "": continue m = _num.match(x) if m is None: continue mon = int(m.group(0)) self.data[mon]=x[m.end():] recvs,self.queue.receivers = self.queue.receivers,[] for r in recvs: mid = getattr(r,"msgid",None) if mid is None or mid in self.data: log("wago",TRACE,"found monitor",r) self.queue.receivers.append(r) else: try: raise DroppedMonitor(mid) except DroppedMonitor as ex: fix_exception(ex) res = r.error(ex) if res is SEND_AGAIN: log("wago",TRACE,"retry monitor",r) self.queue.enqueue(r) else: log("wago",TRACE,"drop monitor",r) assert res is None or res is False, "%s.error returned %s"%(repr(r),repr(res)) return MINE if msg.type is MT_NAK or msg.type is MT_ERROR: simple_event("wago","monitor","error", msg=msg.msg) return MINE return NOT_MINE
def __init__(self, parent, args, name=None, prio=(MIN_PRIO + MAX_PRIO) // 2 + 1): self.prio = prio self.displayname = name self.args = args self.parent = parent if name is None: name = Name("_on", self._get_id()) super(OnEventBase, self).__init__(*name) for k in self.args: if hasattr(k, 'startswith') and k.startswith('*'): self._simple = False # self.name = six.text_type(self.args) # if self.displayname is not None: # self.name += u" ‹"+" ".join(six.text_type(x) for x in self.displayname)+u"›" log(TRACE, "NewHandler", self.id)
def filter_data(self): """Discard outlier values and calculate average""" log("monitor",TRACE,"filter",self.data,"on", self.name) if len(self.data) < self.points: return None avg = sum(float(x) for x in self.data)/len(self.data) if not self.range: return avg data = self.data while True: lo = min(data) hi = max(data) if hi-lo <= self.range: return avg if len(data) == self.points: break new_data = [] extr = None # stored outlier nsum = 0 # new sum dif = None # difference for extr for val in data: ndif = abs(avg-val) if dif is None or dif < ndif: dif = ndif if extr is not None: nsum += extr new_data.append(extr) extr = val else: nsum += val new_data.append(val) data = new_data avg = nsum/len(data) return None
def lineReceived(self, line): log("rrd",TRACE,"recv",repr(line)) msgid = 0 off = 0 mt = MT_OTHER if self.buf is not None: self.buf.append(line) self.lines -= 1 if self.lines == 0: buf,self.buf = self.buf,None self.msgReceived(type=MT_MULTILINE, msg=buf[0],data=buf[1:]) return elif line == "": self.msgReceived(type=MT_OTHER, msg=line) elif line[0] == "-": off=1 errno=0 while off < len(line) and line[off].isdigit(): errno = 10*errno+int(line[off]) off += 1 self.msgReceived(type=MT_ERROR, errno=errno, msg=line[off:].strip()) elif line[0].isdigit(): off=0 lines=0 while off < len(line) and line[off].isdigit(): lines = 10*lines+int(line[off]) off += 1 if lines: self.lines = lines self.buf = [line[off:]] return self.msgReceived(type=MT_ACK, msg=line[off:].strip()) return else: self.msgReceived(type=MT_OTHER, msg=line)
def dataReceived(self, data): """Convert OWFS messages into calls to msgReceived.""" self._data += data while len(self._data) >= self._len: if self._typ is None: version, payload_len, ret_value, format_flags, data_len, offset = struct.unpack( '!6i', self._data[:24]) self._data = self._data[self._len:] log("onewire", DEBUG, "RECV", version, payload_len, ret_value, format_flags, data_len, "x%x" % offset) # 0 253 0 2 252 32774 if offset & 32768: offset = 0 if version != 0: self.error(RuntimeError("Wrong version: %d" % (version, ))) return if payload_len == -1 and data_len == 0 and offset == 0: log("onewire", DEBUG, "RECV", u"… server busy") continue # server busy # if payload_len < 0 or payload_len > 0 and (payload_len < data_len or offset+data_len > payload_len): # self.errReceived(RuntimeError("Wrong length: %d %d %d"%(payload_len,offset,data_len,))) # return if payload_len > self.MAX_LENGTH: self.error( RuntimeError("Length exceeded: %d %d %d" % ( payload_len, offset, data_len, ))) return self._offset = offset if payload_len: self._data_len = data_len else: self._data_len = 0 self._len = payload_len self._typ = ret_value else: # offset seems not to mean what we all think it means #data = self._data[self._offset:self._offset+self._data_len] data = self._data[:self._offset + self._data_len] log("onewire", DEBUG, "RECV", u"…", self._data_len, repr(data)) self._data = self._data[self._len:] typ = self._typ self._typ = None self._len = 24 self.msgReceived(typ=typ, data=data)
def dataReceived(self, data): """Convert OWFS messages into calls to msgReceived.""" self._data += data while len(self._data) >= self._len: if self._typ is None: version, payload_len, ret_value, format_flags, data_len, offset = struct.unpack('!6i', self._data[:24]) self._data = self._data[self._len:] log("onewire",DEBUG,"RECV", version, payload_len, ret_value, format_flags, data_len, "x%x"%offset) # 0 253 0 2 252 32774 if offset & 32768: offset = 0 if version != 0: self.error(RuntimeError("Wrong version: %d"%(version,))) return if payload_len == -1 and data_len == 0 and offset == 0: log("onewire",DEBUG,"RECV", u"… server busy") continue # server busy # if payload_len < 0 or payload_len > 0 and (payload_len < data_len or offset+data_len > payload_len): # self.errReceived(RuntimeError("Wrong length: %d %d %d"%(payload_len,offset,data_len,))) # return if payload_len > self.MAX_LENGTH: self.error(RuntimeError("Length exceeded: %d %d %d"%(payload_len,offset,data_len,))) return self._offset = offset if payload_len: self._data_len = data_len else: self._data_len = 0 self._len = payload_len self._typ = ret_value else: # offset seems not to mean what we all think it means #data = self._data[self._offset:self._offset+self._data_len] data = self._data[:self._offset+self._data_len] log("onewire",DEBUG,"RECV", u"…",self._data_len,repr(data)) self._data = self._data[self._len:] typ = self._typ self._typ = None self._len = 24 self.msgReceived(typ=typ,data=data)
def _incoming(self,msg): """Process an incoming message.""" self.n_rcvd_now += 1 log("conn",TRACE,"incoming", self.__class__.__name__,self.name,msg) self.last_recv = msg self.last_recv_at = now() # i is an optimization for receiver lists that don't change in mid-action handled = False log("msg",TRACE,"recv",self.name,str(msg)) for mq in self.receivers: i = 0 for m in mq: try: r = m.recv(msg) log("msg",TRACE,"recv=",r,repr(m)) if r is ABORT: self.channel.close(False) self.channel = None break elif r is NOT_MINE: continue elif r is MINE or r is SEND_AGAIN: handled = True if len(mq) > i and mq[i] is m: mq.pop(i) else: mq.remove(m) i -= 1 if r is SEND_AGAIN: if m.blocking: self.senders[0].insert(0,m) else: self.senders[m.prio].append(m) else: m.done() self.n_processed_now += 1 break elif r is RECV_AGAIN: handled = True break elif r is SEND_AGAIN: handled = True break elif isinstance(r,MSG_ERROR): raise r else: raise BadResult(m) except Exception as ex: if len(mq) < i and mq[i] is m: mq.pop(i) elif m in self.receivers: mq.remove(m) fix_exception(ex) process_failure(ex) self.channel.close(False) self.channel = None simple_event("msg","error",*self.name, msg=msg) handled = True break i += 1 if not handled: simple_event("msg","unhandled",*self.name, msg=msg)
def done(self, _=None): log("onewire", DEBUG, "doneDIR", self) return super(DIRmsg, self).done()
def _error(self,msg): log("conn",ERROR,self.state,self.__class__.__name__,self.name,str(msg)) self._teardown() process_failure(msg)
def dataReceived(self, data): # child object expect this log("onewire", DEBUG, "done: ", self) if self.result is not None: self.result.set(data)
def _set_state(self,state): log("conn",TRACE,state,self.__class__.__name__,self.name) self.state = state self.last_change = now()
def _handler(self): """\ This is the receiver's main loop. Processing of incoming and outgoing data is serialized so that there will be no problems with concurrency. """ def doReOpen(): m = MsgReOpen() if self.q is not None: self.q.put(m, block=False) state = "open" if self.state == "connected" else "closed" if self.channel is None else "connecting" log("conn",TRACE,"setstate init %s" % (state,)) self.connect_timeout = self.initial_connect_timeout self.attempts = 0 if not self.ondemand and state != "open": doReOpen() while True: msg = self.q.get() if isinstance(msg,MsgSender): self.senders[msg.prio].append(msg) elif isinstance(msg,MsgReceiver): if msg.blocking: self.receivers[msg.prio].insert(0,msg) else: self.receivers[msg.prio].append(msg) elif isinstance(msg,MsgIncoming): self._incoming(msg) elif isinstance(msg,MsgOpenMarker): log("conn",TRACE,"setstate %s %s" % (state,"connected")) state = "connected" self.connect_timeout = self.initial_connect_timeout self.attempts = 0 elif isinstance(msg,MsgReOpen): if self.channel is None: log("conn",TRACE,"setstate %s %s" % (state,"want")) state = "want" elif isinstance(msg,MsgClosed): if self.channel is not None: if state != "waiting" and state != "connecting": log("conn",TRACE,"setstate2 %s %s" % (state,"closed")) state = "closed" self._teardown("ReOpen",external=False) if state == "closed" or state == "connecting": log("conn",TRACE,"setstate %s %s: wait %.3f" % (state,"waiting",self.connect_timeout)) state = "waiting" callLater(True,self.connect_timeout,doReOpen) self._up_timeout() elif isinstance(msg,MsgError): self._error(msg.error) else: raise UnknownMessageType(msg) if self.ondemand and not self.n_outq: continue if state == "want" or state == "closed" and self.ondemand and self.n_outq: log("conn",TRACE,"setstate %s %s" % (state,"connecting")) state = "connecting" self._setup() if self.state != "connected": continue log("msg",TRACE,"states at run",self.state,state) done = False # marker for "don't send any more stuff" for mq in self.receivers: if done: break for m in mq: if m.blocking: log("msg",TRACE,"blocked by",str(m)) done = True if done: continue for mq in self.senders: if done: break while len(mq): if done: break if self.channel is None: break msg = mq.pop(0) log("msg",TRACE,"send",str(msg)) try: r = msg.send(self.channel) except Exception as ex: fix_exception(ex) r = ex else: self.last_sent = msg self.last_sent_at = now() self.n_sent_now += 1 log("msg",TRACE,"send result",r) if r is RECV_AGAIN: if msg.blocking: self.receivers[msg.prio].insert(0,msg) else: self.receivers[msg.prio].append(msg) elif r is SEND_AGAIN: if msg.blocking: self.senders[msg.prio].insert(0,msg) else: self.senders[msg.prio].append(msg) elif isinstance(r,SEND_LATER): raise NotImplementedError("Queueing doesn't work yet") elif isinstance(r,MSG_ERROR): try: raise r except Exception as r: fix_exception(r) process_failure(r) elif isinstance(r,Exception): reraise(r) else: msg.done() if msg.blocking: done = True break # while setting up, only process PRIO_CONNECT messages if state != "connected": log(TRACE,"NotConn",self.senders) break
def down_event(self,external=False,*a,**k): log(TRACE,"!got DOWN_EVENT",*self.name) msg = MsgClosed() self._msg_queue.put(msg) super(xself.cls,self).down_event()
def _dump_tree(self, pre): from moat.logging import log, DEBUG log(DEBUG, "CTX " + pre, six.text_type(self._store)) for p in self._parent: p._dump_tree(pre + " ")
def loseConnection(self): self.lost = True log("parser", DEBUG, "LAST_SYM _drop")
def _update_all(self): log("onewire", TRACE, "start bus update") old_ids = devices.copy() new_ids = {} seen_ids = {} old_bus = set(self.bus_paths.keys()) new_bus = set() def bus_cb(path): if path in old_bus: old_bus.remove(path) else: new_bus.add(path) for dev in self.all_devices(bus_cb): if dev.id in seen_ids: continue seen_ids[dev.id] = dev if dev.id in old_ids: del old_ids[dev.id] else: new_ids[dev.id] = dev n_old = 0 n_dev = 0 for dev in old_ids.values(): if dev.bus is self: n_old += 1 ## Just because something vanishes from the listing ## doesn't mean it's dead; the bus may be a bit unstable # dev.go_down() log("onewire", DEBUG, "Bus unstable?", self.name, dev.id) for dev in devices.values(): if dev.bus is self: n_dev += 1 for dev in old_bus: bp = self.bus_paths.pop(dev) bp.stop() simple_event("onewire", "bus", "down", bus=self.name, path=dev) simple_event("onewire", "bus", "state", self.name, "/".join(dev), bus=self.name, path=dev, state="down") for dev in new_bus: self.bus_paths[dev] = OWFSbuspath(self, dev) simple_event("onewire", "bus", "up", bus=self.name, path=dev) simple_event("onewire", "bus", "state", self.name, "/".join(dev), bus=self.name, path=dev, state="up") # success only, error above simple_event("onewire", "scanned", *self.name, old=n_old, new=len(new_ids), num=n_dev, deprecated=True) simple_event("onewire", "scan", *self.name, run="done", old=n_old, new=len(new_ids), num=n_dev)
def _monitor(self): """This implements a monitor sequence.""" self.steps = 0 self.data = [] self.new_value = None def delay(): if isinstance(self.delay,tuple): sleepUntil(False,time_delta(self.delay)) else: sleepUntil(False,self.delay) try: while self.job and (self.maxpoints is None or self.steps < self.maxpoints): if self.steps and not self.passive: delay() self.steps += 1 try: val = self.one_value(self.steps) except MonitorAgain: pass except Exception as e: fix_exception(e) process_failure(e) break else: try: val = float(val) except (TypeError,ValueError): log("monitor",ERROR,self.name,"not a float:",val) continue if hasattr(self,"factor"): try: val = val * self.factor + self.offset except (TypeError,ValueError) as e: log("monitor",ERROR,self.name,val,self.factor,self.offset) continue self.data.append(val) avg = self.filter_data() if avg is not None: if self.value is None or \ self.diff is None or \ abs(self.value-avg) > self.diff: try: if self.value is not None and \ self.alarm is not None and \ abs(self.value-avg) > self.alarm: simple_event(self.ectx,"monitor","jump",*self.name, avg=avg,value=self.value,alarm=self.alarm) except Exception as e: fix_exception(e) process_failure(e) else: self.new_value = avg return else: log("monitor",TRACE,"More data", self.data, "for", u"‹"+" ".join(six.text_type(x) for x in self.name)+u"›") try: simple_event(self.ectx,"monitor","error",*self.name) except Exception as e: fix_exception(e) process_failure(e) finally: log("monitor",TRACE,"End run", self.name) self.stopped_at = now()
def running(event): log(TRACE, "PY Event called", event)
def not_running(event): log(ERROR, "PY bad event called", event)
def _parseStep(self, t, txt, beg, end, line): from token import NUMBER,NAME,DEDENT,INDENT,OP,NEWLINE,ENDMARKER, \ STRING from moat.tokize import COMMENT, NL self.last_pos = beg if "logger" in self.ctx: self.ctx.logger("T", self.p_state, t, repr(txt), beg, end, repr(line)) if t == COMMENT: return if self.p_state == 0: # begin of statement if t == NAME: self.p_args = [txt] self.p_state = 1 return elif t == DEDENT: self.proc.done() if self.p_stack: self.proc = self.p_stack.pop() return else: raise StopIteration elif t == ENDMARKER: self.proc.done() while self.p_stack: self.proc = self.p_stack.pop() self.proc.done() raise StopIteration elif t in (NL, NEWLINE): self.prompt() return elif t == OP and txt == ".": return # "I am done" elif self.p_state in (1, 2): # after first word if t == NAME: self.p_args.append(txt) self.p_state = 2 return elif t == OP and txt in ("*", "+", "-"): self.p_args.append(txt) self.p_state = 1 return elif t == NUMBER: self.p_args.append(eval(txt, {}, {})) self.p_state = 1 return elif t == STRING: self.p_args.append(eval(txt, {}, {})) self.p_state = 1 return elif t == OP and txt[0] in ("$", "*"): self.p_args.append(txt) self.p_state = 1 return elif t == OP and txt == "." and self.p_state == 2: self.p_state = 5 return elif t == OP and txt == ":": log("parser", TRACE, "RUN2") log("parser", TRACE, self.proc.complex_statement, self.p_args) self.p_state = 3 _ = self.proc.complex_statement(self.p_args) self.p_stack.append(self.proc) self.proc = _ return elif t == NEWLINE: log("parser", TRACE, "RUN3") log("parser", TRACE, self.proc.simple_statement, self.p_args) # defer setting state to zero when pop_after is set # because that would break one-line compound statements # ("wait :for 2"). # On the other hand, setting it later anyway breaks # statements which terminate the parser ("exit") if not self.p_pop_after: self.p_state = 0 self.proc.simple_statement(self.p_args) if self.p_pop_after: self.proc.done() self.proc = self.p_stack.pop() self.p_pop_after = False self.p_state = 0 self.prompt() return elif self.p_state == 3: if t == NEWLINE: self.p_state = 4 self.prompt() return elif t == NAME: self.p_args = [txt] self.p_state = 1 self.p_pop_after = True return else: self.proc = self.p_stack.pop() elif self.p_state == 4: if t == INDENT: self.p_state = 0 return elif t == NEWLINE: # ignore return else: self.proc = self.p_stack.pop() elif self.p_state == 5: if t == NAME: self.p_args[-1] += "." + txt self.p_state = 2 return if self.p_pop_after: self.proc = self.p_stack.pop() self.p_pop_after = False raise SyntaxError("Unknown token %s (%s, state %d) in %s:%d" % (repr(txt), tok_name[t] if t in tok_name else t, self.p_state, self.ctx.filename, beg[0]))
def not_up_event(self,external=False,*a,**k): log(TRACE,"!got NOT_UP_EVENT",*self.name) msg = MsgClosed() self._msg_queue.put(msg) super(xself.cls,self).not_up_event(external=external, **k)
def drop(self, _): log("parser", DEBUG, "LAST_SYM drop") conns.remove(self) self.loseConnection() return _
def up_event(self,*a,**k): log(TRACE,"!got UP_EVENT",*self.name) msg = MsgOpenMarker() self._msg_queue.put(msg) super(xself.cls,self).up_event()