diff --git a/app/fridge.py b/app/fridge.py new file mode 100644 index 0000000..edb0954 --- /dev/null +++ b/app/fridge.py @@ -0,0 +1,15 @@ +class Fridge: + + def __init__(self, name): + self.name = name.decode('utf-8') + self.sensors = list() + + def add_sensor(self, sensor): + self.sensors.append(sensor) + + +class Sensor: + + def __init__(self, name, sensorid): + self.name = name.decode('utf-8') + self.id = sensorid \ No newline at end of file diff --git a/app/gen_test_data_temperature.py b/app/gen_test_data_temperature.py new file mode 100644 index 0000000..3594d39 --- /dev/null +++ b/app/gen_test_data_temperature.py @@ -0,0 +1,26 @@ +import numpy as np +import datetime as dt +import pandas as pa +import ipdb +testdata = np.empty((14400, 7), dtype=object) + +#ipdb.set_trace() + +for n, line in enumerate(reversed(testdata)): + a = (dt.datetime.now() - dt.timedelta(seconds=(300*n))) + line[0] = a + line[1] = np.sin(2.0 * np.pi *20.0 / 14400 * n) * 5 + np.sin(2.0 * np.pi * 2.0 / 14400 * n) * 1.4 + 10 + line[2] = np.sin(2.0 * np.pi *20.0 / 14400 * n) * 4 + np.sin(2.0 * np.pi * 2.0 / 14400 * n) * 1.4 + 13 + line[3] = np.sin(2.0 * np.pi *20.0 / 14400 * n) * 3 + np.sin(2.0 * np.pi * 2.0 / 14400 * n) * 1.4 + 15 + line[4] = np.sin(2.0 * np.pi *30.0 / 14400 * n) * 5 + np.sin(2.0 * np.pi * 3.5 / 14400 * n) * 1 + 10 + line[5] = np.sin(2.0 * np.pi *30.0 / 14400 * n) * 4 + np.sin(2.0 * np.pi * 3.5 / 14400 * n) * 1 + 13 + line[6] = np.sin(2.0 * np.pi *30.0 / 14400 * n) * 3 + np.sin(2.0 * np.pi * 3.5 / 14400 * n) * 1 + 15 + +pdata = pa.DataFrame.from_records(testdata,columns=("time","1","2","3","4","5","6")) +print pdata + +pdata.to_csv("static/testdata.csv", index=False) +#np.savetxt("static/testdata.csv", testdata) + +readdata = pa.read_csv("static/testdata.csv") +print readdata diff --git a/app/plot.py b/app/plot.py index 147b817..0935397 100644 --- a/app/plot.py +++ b/app/plot.py @@ -1,12 +1,16 @@ #import matplotlib #speed? #matplotlib.use('GTKAgg') + from matplotlib import pyplot as plt +from matplotlib import units from matplotlib.dates import WeekdayLocator, DayLocator, HourLocator, DateFormatter, drange, MONDAY import numpy as np from user import User from database import * import multiprocessing as mp - +import pandas as pd +import ipdb +import logging def plot_all_thread(user=None): if user is not None: @@ -21,21 +25,17 @@ def plot_all(user=None): plot_total(user) plot_total() plot_list(4) - print 'plot_all' + logging.info('plot_all') def plot_total(user=None): - print "start plot_total " + str(datetime.datetime.now()) - print 'plot_total' + logging.info("start plot_total") + today = datetime.date.today() delta = datetime.timedelta(days=1) begin = today - datetime.timedelta(weeks=2) dates = drange(begin, today + delta, delta) - #print begin - #print today - #print dates - products = get_products() allconsumptions = [[0 for x in range(len(dates))] for product in products] @@ -94,17 +94,84 @@ def plot_total(user=None): fils = "app/static/total%03d.png" % user.id fill = "app/static/total%03d_big.png" % user.id plt.title(tit) - print "plot plot_total " + str(datetime.datetime.now()) + logging.info("plot plot_total " + str(datetime.datetime.now())) #480x320 fig.set_size_inches(4.8, 3.2) plt.savefig(fils, dpi=100) - print "end plot_total " + str(datetime.datetime.now()) + logging.info("end plot_total " + str(datetime.datetime.now())) #fig.set_size_inches(4.8, 3.2) #plt.savefig(fill, dpi=400) +def plot_log(days, logfiles): + today = datetime.date.today() + delta = datetime.timedelta(days=1) + begin = today - datetime.timedelta(days=days) + dates = drange(begin, today + delta, delta) + + #print begin + #print today + #print dates + + #load all logfiles + data = None + for logfile in logfiles: + try: + d = pd.read_csv("app/static/testdata.csv", parse_dates=[0]) + if data: + data = pd.concat((data, d)) + else: + data = d + except: + logging.error("error while loading file " + logfile) + return 0 + + #ipdb.set_trace() + data = data.set_index(pd.DatetimeIndex(data.time)) + data = data.drop("time", axis=1) + #ipdb.set_trace() + plt.xkcd() + #all columns + for item, frame in data.iteritems(): + f = plt.figure() + #f.patch.set_facecolor("#ccefff") + #f.patch.set_alpha("0.0") + logging.debug("column " + str(item) + " " + frame.name) + plt.plot(data.index.to_pydatetime(), frame, "b") + ax = plt.gca() + #ax.grid(True, linewidth=1.0) + plt.xlim(begin, today) + ax.spines['right'].set_visible(False) + ax.spines['top'].set_visible(False) + ax.yaxis.set_ticks_position('none')#('left') + ax.xaxis.set_ticks_position('none')#('bottom') + + f.autofmt_xdate() + + #plt.tick_params(which='minor', length=4) + #plt.tick_params(which='major', length=5) + #ipdb.set_trace() + ax.fmt_xdata = DateFormatter('%d.%m') + #ax.xaxis.set_major_locator(WeekdayLocator(MONDAY)) + #ax.xaxis.set_major_locator(DayLocator()) + ax.xaxis.set_major_formatter(DateFormatter('%d.%m')) + + + #plt.xlabel('Datum') + #plt.ylabel('Temperatur / C') + outfile = "app/static/log_" + str(item) + ".png" + logging.info("plot plot_total " + str(datetime.datetime.now())) + #480x320 + plt.gcf().set_size_inches(5.3, 2.4) + plt.tight_layout() + plt.savefig(outfile, dpi=70, transparent=True, bbox_inches='tight') + plt.close() + + logging.info("end plot_list " + str(datetime.datetime.now())) + + def plot_list(duration): - print "start plot_list " + str(datetime.datetime.now()) + logging.info("start plot_list " + str(datetime.datetime.now())) today = datetime.datetime.today() begin = today - datetime.timedelta(weeks=duration) @@ -180,11 +247,11 @@ def plot_list(duration): plt.title("Bierliste ("+ str(duration) + " Wochen)") - print "plot plot_list " + str(datetime.datetime.now()) + logging.info("plot plot_list " + str(datetime.datetime.now())) #800x600 fig.set_size_inches(15, 10) plt.savefig('app/static/bierliste_small.png', dpi=72, bbox_inches='tight') #1024x768 #fig.set_size_inches(10.24, 7.68) #plt.savefig('app/static/bierliste.png', dpi=100) - print "end plot_list " + str(datetime.datetime.now()) \ No newline at end of file + logging.info("end plot_list " + str(datetime.datetime.now())) \ No newline at end of file diff --git a/app/settings.py b/app/settings.py index 864cb2d..cd06903 100644 --- a/app/settings.py +++ b/app/settings.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- ################################################################ # Settings # ################################################################ @@ -15,6 +16,7 @@ # ################################################################ +from fridge import Fridge, Sensor class Settings: @@ -40,7 +42,30 @@ class Settings: self.annoyDays = 20 #Automatically send mails every x days (default 20) self.annoyLimit = 100 #Money limit for autoAnnoy (default 100) + ##Data Logging + #Fridge Temperature + self.fridgeLogging = False #Log the fridge temperature (connect temp. sensors before enabling) + self.fridgeTime = 300 #Write fridge temp to file every x seconds + self.fridgeLength = 30 #Length of data log span in days + ##Developer Settings self.debug = False #Show debug output in console + ##Data Logging - Fridges + self.fridges = list() #Do not edit + + #Create an antialcoholic fridge (Antikühlschrank) with 3 sensors (top, middle and bottom temp.) + new_f = Fridge("Antikühlschrank") #make new fridge + new_f.add_sensor(Sensor("Temperatur Oben", "1")) #add sensor 1 as top + new_f.add_sensor(Sensor("Temperatur Mitte", "2")) #add sensor 2 as middle + new_f.add_sensor(Sensor("Temperatur Unten", "3")) #add sensor 3 as bottom + self.fridges.append(new_f) #append to the list of fridges + + #Create an alcoholic fridge with 3 sensors #add more fridges as you like + new_f = Fridge("Bierkühlschrank") + new_f.add_sensor(Sensor("Temperatur Oben", "4")) + new_f.add_sensor(Sensor("Temperatur Mitte", "5")) + new_f.add_sensor(Sensor("Temperatur Unten", "6")) + self.fridges.append(new_f) + settings = Settings() diff --git a/app/static/style.css b/app/static/style.css index 520d16a..53d25c9 100644 --- a/app/static/style.css +++ b/app/static/style.css @@ -122,4 +122,38 @@ input[type=button], input[type=submit], input[type=reset] { text-decoration: none; margin: 8px 0px; cursor: pointer; +} + +/* SECTION: FRIDGE */ + +div.fridge { background-color:#FFCC00; + margin:20px; + padding:10px; + padding-left:15px; + padding-right:15px; + padding-bottom:20px; + border-radius:5px; + border:4px solid black; + float: left; +} + +div.fridge_top { color:black; + padding:2px; + text-align:center; +} + +div.fridge_bottom { background-color:#AACCFF; + padding:2px; + border-radius:4px; + border:3px solid black; +} + +div.fridge_sensor { background-color:#E3E6FF; /*#CCEFFF;*/ + text-align:center; + min-height: 170px; + padding:3px; + border-radius:2px; + border:1px; + border-color:#CCCCCC; + margin: 3px } \ No newline at end of file diff --git a/app/views.py b/app/views.py index 4360a16..f39ac0e 100644 --- a/app/views.py +++ b/app/views.py @@ -1,9 +1,12 @@ +# -*- coding: utf-8 -*- + from check_rights import * from flask import render_template, request, redirect, session, send_from_directory from app import app from database import * from plot import * from user import User +from fridge import Fridge, Sensor from product import Product from send_email import send_email, send_emails from consumption import Consumption @@ -62,6 +65,12 @@ def logout(): return redirect('/') +@app.route('/fridges') +def fridges(): + plot_log(30, ("static/testdata.csv",)) + return render_template('fridges.html', fridges=settings.fridges, user=get_user_by_name(session.get('name'))) + + @app.route('/manage_users') @requires_baron def manage_users(): @@ -179,10 +188,8 @@ def manage_beverages_edit(name=None): p.isshown = False pic = request.files['file'] - print pic.filename if pic: extension = pic.filename.rsplit('.', 1)[1].lower() - print extension if extension == "png" or extension == "jpg": pic.seek(0) # Move cursor back to beginning so we can write to disk fpath = os.path.join("./app/static/", "product_%s.png" % p.name) @@ -201,7 +208,7 @@ def manage_beverages_add(): if request.method == 'POST': p = Product() error = None - print request + logging.info(request) p.name = request.form['name'] #if request.form['price'].isnumeric(): p.price = float(request.form['price']) @@ -214,10 +221,10 @@ def manage_beverages_add(): p.isshown = False pic = request.files['file'] - print pic.filename + logging.info(pic.filename) if pic: extension = pic.filename.rsplit('.', 1)[1].lower() - print extension + logging.info(extension) if extension == "png" or extension == "jpg": pic.seek(0) # Move cursor back to beginning so we can write to disk fpath = os.path.join("./app/static/", "product_%s.png" % p.name) @@ -277,7 +284,7 @@ def billing(): payment = float(request.form[formname]) if payment != 0: add_deposit(user.name, payment) - print "%s payed %d" % (user.name, payment) + logging.info("%s payed %d" % (user.name, payment)) debt = [0 for user in users] users = get_users() # refresh users for correct viewing of autounblacking for user in users: