def formhandler(): ''' Handle form submission ''' tm = time.perf_counter() if 'REMOTE_ADDR' in bottle.request.environ: ip = bottle.request.environ.get('REMOTE_ADDR') else: ip = None logger.info("==== menu handler from %s =====:\n%s" % (ip, bottle.request.body.read())) selqs = bottle.request.forms.getall('quantities') src = bottle.request.forms.get('source') tbcknm = bottle.request.forms.get('tmback') cursXpos = bottle.request.forms.get('cursorPos') jdtill = bottle.request.forms.get('jdtill') evtDescr = bottle.request.forms.get('evtDescr') evtData = bottle.request.forms.get('evtData') try: ndays = next(tb for tb, tup in tmBACKs.items() if tbcknm in tup[0]) except StopIteration: ndays = 5 jdofs = (plXMARG + plWIDTH - int(cursXpos)) / plWIDTH * ndays # cursor pos giving time offset if jdtill: jdtill = float(jdtill) # preserve actual time frame else: jdtill = julianday() jdcursor = jdtill - jdofs if evtDescr and evtDescr != 'comment': # define event at cursor root = sys.modules['__main__'].__file__ logger.info('received event descr %s at jd:%s' % (evtDescr, jdcursor)) dbStore.setEvtDescription(jdcursor, evtDescr, root=root) else: # place right side at cursor jdtill = jdcursor if abs(jdtill - julianday()) < ndays / 5.0: jdtill = julianday() # adjust to now when close else: logger.info("adjusting jd %f with ofs:%f evt:%s" % (jdtill, jdofs, evtDescr)) statbar = bottle.request.forms.get('statbar') logger.info("statbar=%s" % statbar) logger.info( "menu response(t:%s):qtt=%s src=%s jd=%s ndys=%s cPos=%s evtData=%s" % (time.perf_counter() - tm, selqs, src, prettydate(jdtill), tbcknm, cursXpos, evtData)) bottle.response.set_cookie(COOKIE, json.dumps((src, selqs, ndays)), max_age=AN1) return bottle.template(TPL, redraw(src, selqs, jdtill, ndays))
def logi(self, ikey, numval, strval=None, tstamp=None): ''' save value to the database ''' if tstamp is None: tstamp = round(time.time(),0) # granularity 1s logger.debug('logging %s (%g) @jd:%.6f' % (self.qname(ikey),numval,julianday(tstamp))) try: self.execute('INSERT INTO logdat (ddJulian,quantity,numval) VALUES (?,?,?)', (julianday(tstamp),ikey,numval)) if not strval is None: self.execute('UPDATE logdat SET strval="%s" WHERE ddJulian=? AND quantity=?' % strval,(julianday(tstamp),ikey)) except OperationalError: logger.error("unable to update database with id:%d at jd:%.6f" % (ikey,julianday(tstamp))) except KeyboardInterrupt: raise except Exception: logger.exception("unknown !!!")
def index(name=TITLE): ''' standard opening page (with settings from cookie or default) ''' if 'REMOTE_ADDR' in bottle.request.environ: ip = bottle.request.environ.get('REMOTE_ADDR') else: ip = None tm = time.perf_counter() logger.info("===== index request:%s from %s=====" % (bottle.request.body.read(), ip)) if bottle.request.query.title: bottle.redirect('/menu') srcs = list(dbStore.sources()) src = srcs[0] quantIds = [] cookie = bottle.request.get_cookie(COOKIE) if cookie: logger.info('using cookie :"%s"' % cookie) cookie = list(json.loads(cookie)) cookie.extend([None, None, None]) src, selqs, ndays = tuple(cookie[:3]) else: selqs = typnames(dbStore.quantities( [src], prop=2))[:2] # quantity typs that are in src ndays = 4 bottle.response.set_cookie(COOKIE, json.dumps((src, selqs, ndays)), max_age=AN1) logger.info("src:%s,selqs:%s len:%d" % (src, selqs, len(selqs))) if len(selqs) == 0 or len(selqs) > 15: selqs = ['temperature'] #page = dict(menitms=buildMenu(srcs,src,typnames(dbStore.quantities(prop=2)),selqs,ndays)) #page = redraw(src,selqs,julianday()) jdtill = julianday() page = redraw(src, selqs, jdtill, ndays) page.update(dict(title=name, footer=__copyright__) ) #jdtill=julianday(),ndays=ndays,grQuantIds=quantIds)) logger.debug("index page:(t:%s)\n%s\n" % (time.perf_counter() - tm, page)) return bottle.template(TPL, page)
def fetchiavg(self, ikey, tstep=30, daysback=100, jdend=None, source=None): ''' fetch averaged interval values from the database, takes averaged numval of name over tstep minutes intervals''' where ="" if not source is None: where=" AND source='%s'" % source if isinstance(ikey, tuple): where+=" AND quantity IN (%s)" % ','.join(map(str,ikey)) else: # len(ids)==1: where+=" AND quantity=%d" % ikey if jdend is None: jdend=julianday() sql = "SELECT ROUND(ddJulian*?)/? AS dd,AVG(numval) AS nval,COUNT(*) AS cnt,source,type " \ "FROM logdat AS ld,quantities AS qu " \ "WHERE active AND qu.ID=ld.quantity AND ddJulian>? AND ddJulian<? %s " \ "GROUP BY quantity,source,dd " \ "ORDER BY ddJulian;" % (where,) try: interval=1440/tstep # minutes per day = 1440 return self.execute(sql, (interval,interval,jdend-daysback,jdend)) except KeyboardInterrupt: raise except Exception: logger.exception("unknown!!!") # probably locked
def check_quantity(self,tstamp,quantity,val): ''' filters, validates, averages, checks, quantity results calls accept_result when quantity rules are fullfilled to be called by receive_message ''' if quantity not in self._servmap: logger.info("unknown quantity:%s val=%s in %s" % (quantity,val,self.manufacturer)) #self.servmap[quantity] = {'typ':DEVT['unknown']} return if self.qtype(quantity)>=DEVT['secluded']: # ignore return if isinstance(val, collections.Sequence): logger.warning('not numeric %d = %s' % (quantity,val)) if self.qInRng(quantity,val)==False: logger.warning("quantity out of range %s" % quantity) return else: self.actual[quantity] = {qVAL:val, qSTMP:tstamp} if sampleCollector.signaller: if sampleCollector.signaller.checkEvent(quantity, val): # handle event by polling sampleCollector.signaller.signal(quantity, val) if self.qIsCounting(quantity): if quantity in self.average and val>0: # only first and pos edge self.average[quantity][qVAL] += val self.average[quantity][qCNT] +=1 else: self.average[quantity] = [val,1,tstamp] self.accept_result(tstamp, quantity) logger.info('(%s) cnt val=%s quantity=%s tm=%s since=%.6g' % (quantity,val, self.qname(quantity), prettydate(julianday(tstamp)), self.sinceAccept(quantity))) elif quantity in self.average: n = self.average[quantity][qCNT] avg = self.average[quantity][qVAL] / n if (n>=self.minNr and abs(val-avg)>abs(avg*self.minDevPerc/100)) or n>=self.maxNr: logger.info('(%s) n=%d avg=%g val=%s quantity=%s devPrc=%g>%g tm=%s since=%.6g' % (quantity,n,avg,val, self.qname(quantity), abs(val-avg)/avg*100 if avg>0 else 0.0, self.minDevPerc, prettydate(julianday(tstamp)), self.sinceAccept(quantity))) self.accept_result((tstamp+self.average[quantity][qSTMP])/2, quantity) self.average[quantity] = [val,1,tstamp] else: self.average[quantity][qVAL] += val self.average[quantity][qCNT] += 1 if abs(avg)>0: logger.debug('quantity:%d avgCount:%d devperc:%.6g ' % (quantity,self.average[quantity][qCNT], (val-avg)/avg*100) ) else: # first avg val self.average[quantity] = [val,1,tstamp] if self.maxNr<=1: self.accept_result(tstamp, quantity) logger.info('accepting one val=%s quantity=%s(%s) tm=%s' % (val,self.qname(quantity),quantity, prettydate(julianday(tstamp))))