From 770ba5201f5c60b2bb36602ff9d359f641e33125 Mon Sep 17 00:00:00 2001 From: Yves Fischer Date: Sun, 23 Oct 2011 21:14:40 +0200 Subject: Charting with flask, rgraph and custom "timeseries database" --- schall/app.py | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 schall/app.py (limited to 'schall/app.py') diff --git a/schall/app.py b/schall/app.py new file mode 100644 index 0000000..657d44d --- /dev/null +++ b/schall/app.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# coding: utf-8 +# vim: ai ts=4 sts=4 et sw=4 +import time +import math +import json + +from octopus import * +import timeseries + +from gevent.wsgi import WSGIServer +from flask import render_template, Flask, session, redirect, url_for, escape, request + +import gevent +import gevent.event +import gevent.monkey +gevent.monkey.patch_all() + +class SyncDB(timeseries.DBSimpleInt): + def __init__(self,*args): + timeseries.DBSimpleInt.__init__(self, *args) + self.semaphore = gevent.coros.Semaphore() + + def get(self, key): + with self.semaphore: + return timeseries.DBSimpleInt.get(self, key) + + def set(self, key, value): + with self.semaphore: + return timeseries.DBSimpleInt.set(self, key, value) + +class Octopus(gevent.Greenlet): + OCTOPUS_IO_PIN = 33 + ADC_REV_MODE = 2 + ADC_REV_MV = 5000 + ADC_MAX_STEP = 1024 + OV_FACTOR = 4.0 + + def __init__(self,db): + gevent.Greenlet.__init__(self) + self.db = db + self.op = octopus_context() + octopus_init(self.op) + octopus_open(self.op) + octopus_adc_init(self.op, Octopus.OCTOPUS_IO_PIN) + octopus_adc_ref(self.op, Octopus.ADC_REV_MODE) + + def _run(self): + while True: + start = time.time() + value = octopus_adc_get(self.op, Octopus.OCTOPUS_IO_PIN) + value_mv = ((Octopus.ADC_REV_MV/Octopus.ADC_MAX_STEP) * value) / Octopus.OV_FACTOR + value_dba = value_mv / 10.0 # messgerät gibt je dbA 10mV aus + print "{3:s} {4:d} 0x{0:=x}, {1:3.2f}mV, {2:2.2f}dbA".format(value, + round(value_mv,2), + round(value_dba,2), + time.strftime("%H:%M:%S." + "%03d" % ( round( ( start - math.floor(start) )*1000) )), + timeseries.time_ms()) + self.value = value_dba + if value_dba > self.db[timeseries.time_ms()]: + self.db[timeseries.time_ms()] = value_dba + stop = time.time() + + gevent.sleep( abs( 0.5 - ( stop - start ) ) ) + +db = SyncDB(10*timeseries.C.INT_SEC, timeseries.C.INT_DAY, "data", "octopus") + +octopus = Octopus(db) + +app = Flask(__name__) +app.debug = True + +@app.route("/") +def app_index(): + return render_template("index.html") + +@app.route("/now") +def app_now(): + value = db[timeseries.time_ms()] or db[timeseries.time_ms() - db.interval] + return json.dumps({'ts':timeseries.time_ms(), 'value':octopus.value}) + +@app.route("/range/") +@app.route("/range/") +@app.route("/range//") +@app.route("/range///") +def app_range(r_from=None, r_to=None, count=1000): + if not r_from: + r_to = timeseries.time_ms() + r_from = r_to - (1000 * db.interval) + + if not r_to: + r_to = timeseries.time_ms() + + assert count < 10000 + assert r_to - r_from <= (timeseries.C.INT_DAY * 2), "r_to - r_from = %s < %s"%(r_to-r_from, timeseries.C.INT_DAY * 2) + assert r_to - r_from > db.interval, "r_to - r_from = %s > "%(r_to-r_from, db.interval) + + values = [] + step = int( math.ceil( (r_to - r_from) / float(count) ) ) + for ts in range(r_from, r_to, step): + value = 0 + i = ts + while i < ts + step: + value = max(db[i], value) + i += db.interval + + if value == 0: + value = None + values.append(value) + + values.reverse() + return json.dumps(values) + +if __name__ == "__main__": + octopus.start() + + http_server = WSGIServer(('', 8000), app) + http_server.start() + + http_server._stopped_event.wait() + octopus.wait() -- cgit v1.2.1