This commit is contained in:
Ulrich Knechtelsdorfer
2016-07-03 20:32:19 +02:00
13 changed files with 230 additions and 41 deletions

130
app/datalog.py Normal file
View File

@@ -0,0 +1,130 @@
import numpy as np
import datetime as dt
import pandas as pa
import time
#import ipdb
import signal
import thread
import logging
import atexit
import os
# i2c io pins
P_SCK = 3
P_SDA = 2
P_BAUD = 50000
# sensor data
SENSOR_BASEID = 0x48
SENSOR_DATALEN = 2
# i2c commands for pigpio software i2c
I2C_END = 0
I2C_START = 2
I2C_STOP = 3
I2C_SET_ADDR = 4
I2C_READ = 6
try:
import pigpio
except:
logging.fatal("PIGPIO library could not be loaded, install PIGPIO to read sensor data or disable data logging in the settings!")
exit()
class DataLogger:
def __init__(self):
self.ioif = None
self.logging = True
signal.signal(signal.SIGINT, self.cleanup)
logging.info("Data Logger created")
thread.start_new_thread(self.log_data, ())
#self.log_data()
def log_data(self):
# pigpio
self.ioif = pigpio.pi()
# software i2c
try:
self.ioif.bb_i2c_open(P_SDA, P_SCK, P_BAUD)
except:
logging.error("bus already open")
self.ioif.bb_i2c_close(P_SDA)
self.ioif.bb_i2c_open(P_SDA, P_SCK, P_BAUD)
logging.info("Data Logger started")
log = 0
data_fast = np.zeros(8)
data_perm = np.zeros(8)
n_fast = 1
n_perm = 1
while logging:
logging.info("Data Logger logging")
columns = list(("time", ))
for i in range(SENSOR_BASEID, SENSOR_BASEID + 8):
(count, data) = self.ioif.bb_i2c_zip(P_SDA, [I2C_SET_ADDR, i, I2C_START, I2C_READ, SENSOR_DATALEN, I2C_STOP, I2C_END])
columns.append(str(i))
if count > 1:
sign = 1
if data[0] > 128:
print "sign"
data[0] = data[0]-128
sign = -1
data_fast[i-SENSOR_BASEID] += sign * (int(data[0]) + (int(data[1]) / 256.0))
data_perm[i-SENSOR_BASEID] += sign * (int(data[0]) + (int(data[1]) / 256.0))
else:
data_fast[i-SENSOR_BASEID] = np.nan
data_perm[i-SENSOR_BASEID] = np.nan
time.sleep(0.05)
infoline = np.empty((1, 9), dtype=object)
if n_fast % 10 == 0:
infoline[0, 1:9] = data_fast[0:8] / n_fast
n_fast = 0
infoline[0, 0] = dt.datetime.now()
pdataline = pa.DataFrame.from_records(infoline, columns=columns)
self.savetofile(False, pdataline)
data_fast = np.zeros(8)
if n_perm % 100 == 0:
infoline[0, 1:9] = data_perm[0:8] / n_perm
n_perm = 0
infoline[0, 0] = dt.datetime.now()
pdataline = pa.DataFrame.from_records(infoline, columns=columns)
self.savetofile(True, pdataline)
data_perm = np.zeros(8)
n_fast += 1
n_perm += 1
def savetofile(self, permanent, data):
if permanent:
date = dt.datetime.now().strftime('%Y%m%d')
exists = os.path.isfile('app/static/logdata_' + date + '.csv')
with open('app/static/logdata_' + date + '.csv', 'a+') as f:
data.to_csv(f, header=not exists, index=False)
else:
exists = os.path.isfile('/tmp/baroness_logdata_fast.csv')
with open('/tmp/baroness_logdata_fast.csv', 'a+') as f:
data.to_csv(f, header=not exists, index=False)
def cleanup(self):
self.logging = False
logging.info("Data logger closed")
self.ioif.bb_i2c_close(P_SDA)
if __name__ == "__main__":
#for standalone mode
print "creating datalogger"
logger = DataLogger()
while(1):
time.sleep(1)

View File

@@ -1,15 +1,60 @@
#import matplotlib #speed? import matplotlib #speed?
#matplotlib.use('GTKAgg') matplotlib.use('TkAgg')
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
from matplotlib import units from matplotlib import units
from matplotlib import patheffects
from matplotlib.dates import WeekdayLocator, DayLocator, HourLocator, DateFormatter, drange, MONDAY from matplotlib.dates import WeekdayLocator, DayLocator, HourLocator, DateFormatter, drange, MONDAY
from matplotlib import rcParams as rcp
import numpy as np import numpy as np
from user import User from user import User
from database import * from database import *
import multiprocessing as mp import multiprocessing as mp
import thread
import pandas as pd import pandas as pd
import logging import logging
import time
import glob
class Plotter:
def __init__(self):
logging.info("Plotter started!")
self.joblist = list()
self.active = True
thread.start_new_thread(self.refresh, ())
def refresh(self):
ptime = 0
while self.active:
logging.info("Plotter plotting stuff")
logfiles = list()
logfiles += glob.glob("app/static/logdata*.csv")
logfiles.append("/tmp/baroness_logdata_fast.csv")
print logfiles
if logfiles:
plot_log(logfiles, hours = 4)
# plotter not fully integrated yet
#if ptime % 30 or self.joblist:
# plot_total()
# plot_list(4)
# for u in self.joblist:
# plot_total(u)
# self.joblist = list()
ptime += 1
time.sleep(10)
def addplot(self, user):
logging.info("Plotter add user " + user.name)
self.joblist.append(user)
def stop(self):
logging.info("Plotter stop!")
self.active = False
def plot_all_thread(user=None): def plot_all_thread(user=None):
if user is not None: if user is not None:
@@ -93,31 +138,25 @@ def plot_total(user=None):
fils = "app/static/total%03d.png" % user.id fils = "app/static/total%03d.png" % user.id
fill = "app/static/total%03d_big.png" % user.id fill = "app/static/total%03d_big.png" % user.id
plt.title(tit) plt.title(tit)
logging.info("plot plot_total " + str(datetime.datetime.now())) logging.info("Plot plot_total " + str(datetime.datetime.now()))
#480x320 #480x320
fig.set_size_inches(4.8, 3.2) fig.set_size_inches(4.8, 3.2)
plt.savefig(fils, dpi=100) plt.savefig(fils, dpi=100)
logging.info("end plot_total " + str(datetime.datetime.now())) logging.info("Plot: End plot_total " + str(datetime.datetime.now()))
#fig.set_size_inches(4.8, 3.2) #fig.set_size_inches(4.8, 3.2)
#plt.savefig(fill, dpi=400) #plt.savefig(fill, dpi=400)
def plot_log(days, logfiles): def plot_log(logfiles, hours):
today = datetime.date.today() end = datetime.datetime.now()
delta = datetime.timedelta(days=1) begin = end - datetime.timedelta(hours=hours)
begin = today - datetime.timedelta(days=days)
dates = drange(begin, today + delta, delta)
#print begin
#print today
#print dates
#load all logfiles #load all logfiles
data = None data = None
for logfile in logfiles: for logfile in logfiles:
try: try:
d = pd.read_csv("app/static/testdata.csv", parse_dates=[0]) d = pd.read_csv(logfile, parse_dates=[0])
if data: if data is not None:
data = pd.concat((data, d)) data = pd.concat((data, d))
else: else:
data = d data = d
@@ -126,53 +165,60 @@ def plot_log(days, logfiles):
return 0 return 0
#ipdb.set_trace() #ipdb.set_trace()
data = data.sort('time')
data = data[data.time > begin]
data = data.set_index(pd.DatetimeIndex(data.time)) data = data.set_index(pd.DatetimeIndex(data.time))
data = data.drop("time", axis=1) data = data.drop("time", axis=1)
#ipdb.set_trace() #ipdb.set_trace()
plt.xkcd() plt.xkcd()
rcp['path.effects'] = [patheffects.withStroke(linewidth=0)]
#all columns #all columns
for item, frame in data.iteritems(): for item, frame in data.iteritems():
if frame is None or frame.empty or frame.isnull().values.all():
continue
f = plt.figure() f = plt.figure()
#f.patch.set_facecolor("#ccefff") #f.patch.set_facecolor("#ccefff")
#f.patch.set_alpha("0.0") #f.patch.set_alpha("0.0")
logging.debug("column " + str(item) + " " + frame.name) logging.debug("column " + str(item) + " " + frame.name)
plt.plot(data.index.to_pydatetime(), frame, "b") plt.plot(data.index.to_pydatetime(), frame)#"b"
ax = plt.gca() ax = plt.gca()
#ax.grid(True, linewidth=1.0) #ax.grid(True, linewidth=1.0)
plt.xlim(begin, today) #plt.xlim(begin, end)
ax.spines['right'].set_visible(False) #ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False) #ax.spines['top'].set_visible(False)
ax.yaxis.set_ticks_position('none')#('left') ax.yaxis.set_ticks_position('none')#('left')
ax.xaxis.set_ticks_position('none')#('bottom') ax.xaxis.set_ticks_position('none')#('bottom')
f.autofmt_xdate() try: #might not work if few data available
f.autofmt_xdate()
#plt.tick_params(which='minor', length=4) #plt.tick_params(which='minor', length=4)
#plt.tick_params(which='major', length=5) #plt.tick_params(which='major', length=5)
#ipdb.set_trace() #ipdb.set_trace()
ax.fmt_xdata = DateFormatter('%d.%m') #ax.fmt_xdata = AutoDateFormatter('%d.%m/%H')
#ax.xaxis.set_major_locator(WeekdayLocator(MONDAY)) #ax.xaxis.set_major_locator(WeekdayLocator(MONDAY))
#ax.xaxis.set_major_locator(DayLocator()) ax.xaxis.set_major_locator(AutoDateLocator())
ax.xaxis.set_major_formatter(DateFormatter('%d.%m')) ax.xaxis.set_major_formatter(AutoDateFormatter(defaultfmt='%d.%m'))
#f.autofmt_xdate()
except:
logging.warning("Plot: Few data!")
#plt.xlabel('Datum') #plt.xlabel('Datum')
#plt.ylabel('Temperatur / C') #plt.ylabel('Temperatur / C')
outfile = "app/static/log_" + str(item) + ".png" outfile = "app/static/log_" + str(item) + ".png"
logging.info("plot plot_total " + str(datetime.datetime.now())) logging.info("Plot plot_log " + str(datetime.datetime.now()))
#480x320 #480x320
plt.gcf().set_size_inches(5.3, 2.4) plt.gcf().set_size_inches(5.3, 2.4)
plt.tight_layout() plt.tight_layout()
plt.savefig(outfile, dpi=70, transparent=True, bbox_inches='tight') plt.savefig(outfile, dpi=70, transparent=True, bbox_inches='tight')
plt.close() plt.close()
logging.info("end plot_list " + str(datetime.datetime.now())) logging.info("Plot: End plot_log " + str(datetime.datetime.now()))
def plot_list(duration): def plot_list(duration):
logging.info("start plot_list " + str(datetime.datetime.now())) logging.info("Plot: Start plot_list " + str(datetime.datetime.now()))
today = datetime.datetime.today() end = datetime.datetime.now()
begin = today - datetime.timedelta(weeks=duration) begin = end - datetime.timedelta(weeks=duration)
users = get_users() users = get_users()
products = get_products() products = get_products()
@@ -246,11 +292,11 @@ def plot_list(duration):
plt.title("Bierliste ("+ str(duration) + " Wochen)") plt.title("Bierliste ("+ str(duration) + " Wochen)")
logging.info("plot plot_list " + str(datetime.datetime.now())) logging.info("Plot plot_list " + str(datetime.datetime.now()))
#800x600 #800x600
fig.set_size_inches(15, 10) fig.set_size_inches(15, 10)
plt.savefig('app/static/bierliste_small.png', dpi=72, bbox_inches='tight') plt.savefig('app/static/bierliste_small.png', dpi=72, bbox_inches='tight')
#1024x768 #1024x768
#fig.set_size_inches(10.24, 7.68) #fig.set_size_inches(10.24, 7.68)
#plt.savefig('app/static/bierliste.png', dpi=100) #plt.savefig('app/static/bierliste.png', dpi=100)
logging.info("end plot_list " + str(datetime.datetime.now())) logging.info("Plot: End plot_list " + str(datetime.datetime.now()))

View File

@@ -1,3 +1,4 @@
import logging
try: try:
import MFRC522 import MFRC522
except: except:
@@ -6,14 +7,13 @@ except:
import signal import signal
import thread import thread
import time import time
import logging
class RFID: class RFID:
def __init__(self, callbackf): def __init__(self, callbackf):
logging.info("RFID Reader initialized!") logging.info("RFID Reader initialized!")
self.reader = MFRC522.MFRC522() self.reader = MFRC522.MFRC522(spd=500000)
signal.signal(signal.SIGINT, self.stop) signal.signal(signal.SIGINT, self.stop)
self.callback = callbackf self.callback = callbackf
self.loop = True self.loop = True

View File

@@ -6,6 +6,11 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=500"> <meta name="viewport" content="width=500">
<!--<meta name="viewport" content="width=device-width, initial-scale=1.0">--> <!--<meta name="viewport" content="width=device-width, initial-scale=1.0">-->
<meta Http-Equiv="Cache-Control" Content="no-cache">
<meta Http-Equiv="Pragma" Content="no-cache">
<meta Http-Equiv="Expires" Content="0">
<meta Http-Equiv="Pragma-directive: no-cache">
<meta Http-Equiv="Cache-directive: no-cache">
<link rel="stylesheet" type="text/css" href="/static/style.css"> <link rel="stylesheet" type="text/css" href="/static/style.css">
{% if title %} {% if title %}
<title> {{ title }} - Baroness </title> <title> {{ title }} - Baroness </title>

View File

@@ -17,7 +17,7 @@
{% set fils = "log_%s.png" % sensor.id %} {% set fils = "log_%s.png" % sensor.id %}
<img src="{{ url_for('static', filename=fils) }}" /><br> <img src="{{ url_for('static', filename=fils) }}" /><br>
</div> </div>
{% endfor %}b {% endfor %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}

View File

@@ -67,7 +67,6 @@ def logout():
@app.route('/fridges') @app.route('/fridges')
def 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'))) return render_template('fridges.html', fridges=settings.fridges, user=get_user_by_name(session.get('name')))

Binary file not shown.

BIN
case/abstandh.stl Normal file

Binary file not shown.

Binary file not shown.

BIN
case/backside.stl Normal file

Binary file not shown.

Binary file not shown.

BIN
case/baroness.stl Normal file

Binary file not shown.

9
run.py
View File

@@ -5,6 +5,9 @@ from os import urandom
from app import gui from app import gui
import thread import thread
import logging import logging
from app import settings
from app import datalog
from app import plot
if __name__ == '__main__': if __name__ == '__main__':
@@ -15,6 +18,12 @@ if __name__ == '__main__':
logging.info("Baroness started!") logging.info("Baroness started!")
print "Baroness started: logging to ", logfile print "Baroness started: logging to ", logfile
#start data logging
if settings.settings.fridgeLogging:
logger = datalog.DataLogger()
#start plot thread
plotter = plot.Plotter()
#start gui #start gui
wx = wx.App() wx = wx.App()