287 lines
8.3 KiB
Python
Executable File
287 lines
8.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
from bottle import get,post,request,Bottle,run,template,static_file
|
|
import threading,time,json,zlib,gnupg,socket,psutil,os,sys,pymysql,queue,_thread,matplotlib.pyplot as plt,matplotlib.cm as cm,numpy
|
|
|
|
payload_haus=["wasser","gas","kwh_haus","kwh_herd"]
|
|
payload_kfz=["km","volumen","preis"]
|
|
#gpg=gnupg.GPG('/usr/bin/gpg',gnupghome='/home/pi/.gnupg')
|
|
gpg=gnupg.GPG()
|
|
|
|
pathname = os.path.dirname(sys.argv[0])
|
|
abspath=os.path.abspath(pathname)
|
|
configfile=abspath+"/config.json"
|
|
try:
|
|
cf=open(configfile,"r")
|
|
except:
|
|
cf=open(configfile+".template","r")
|
|
|
|
log_conf=json.load(cf)
|
|
cf.close()
|
|
|
|
parameter={"device":socket.gethostname(),"allowed_ip":{"127.0.0.1":"25A4CF79414F10FD"},"gpg_keyid":"25A4CF79414F10FD"}
|
|
for n in parameter:
|
|
if n in log_conf:
|
|
parameter[n]=log_conf[n]
|
|
if "sqlserver" in log_conf:
|
|
hostname="banana"
|
|
if "host" in log_conf['sqlserver']:
|
|
hostname=log_conf['sqlserver']['host']
|
|
port=24049
|
|
if "port" in log_conf['sqlserver']:
|
|
port=int(log_conf['sqlserver']['port'])
|
|
|
|
clientlist=parameter['allowed_ip']
|
|
try:
|
|
mydb=pymysql.connect(read_default_file="~/.my.cnf",database="rasolar")
|
|
except:
|
|
clientlist=parameter['allowed_ip']
|
|
else:
|
|
mycursor=mydb.cursor(pymysql.cursors.DictCursor)
|
|
mycursor.execute("select ip,keyid from clients;")
|
|
myclientlist=mycursor.fetchall()
|
|
if len(myclientlist)>0:
|
|
tcl={}
|
|
for i in myclientlist:
|
|
if len(gpg.list_keys(i['keyid']))>0:
|
|
tcl[i['ip']]=i['keyid']
|
|
if len(tcl)>0:
|
|
clientlist=tcl
|
|
|
|
#sqlinsert="insert into measures (time,id,value) values ({0:d},{1:d},{2:d})"
|
|
sqlinsert="insert into measures (time,id,value) values "
|
|
|
|
|
|
measdata={}
|
|
|
|
_HASH="hash"
|
|
_SIGNEDGPG="signed_gpg"
|
|
_PAYLOAD="payload"
|
|
_MEASURES="measure"
|
|
_BEGINSIGNATURE="-----BEGIN PGP SIGNATURE-----"
|
|
_BEGINMESSAGE="-----BEGIN PGP SIGNED MESSAGE-----"
|
|
_BEGINHASH="Hash:"
|
|
_JSONDATA="data"
|
|
_JSONSIGNEDDATA="signed_data"
|
|
_JSONENCRYPTDATA="encrypted_data"
|
|
|
|
def analyse_jsonin(json_in,hash_id):
|
|
measdata={}
|
|
if _JSONDATA in json_in:
|
|
measdata=json_in[_JSONDATA]
|
|
if _JSONSIGNEDDATA in json_in:
|
|
vpgp=gpg.verify(json_in[_JSONSIGNEDDATA])
|
|
if hash_id != vpgp.key_id:
|
|
print("signature does not fit hash id")
|
|
else:
|
|
signed_in=json_in[_JSONSIGNEDDATA].split("\n")
|
|
signed_in[signed_in.index(_BEGINSIGNATURE):]=""
|
|
del signed_in[signed_in.index(_BEGINMESSAGE)]
|
|
del signed_in[signed_in.index("")]
|
|
for h in signed_in:
|
|
if _BEGINHASH in h:
|
|
del signed_in[signed_in.index(h)]
|
|
if len(signed_in)>0:
|
|
measdata=json.loads(signed_in[0])
|
|
if _JSONENCRYPTDATA in json_in:
|
|
dpgp=gpg.decrypt(json_in[_JSONENCRYPTDATA])
|
|
if hash_id != dpgp.key_id:
|
|
print("signature of encrypted data does not fit hash id")
|
|
else:
|
|
measdata=json.loads(dpgp.data)
|
|
if len(measdata)==0:
|
|
print("no data available")
|
|
else:
|
|
_thread.start_new_thread(insert_sql,(measdata,))
|
|
|
|
def insert_sql(measdata):
|
|
tsi=sqlinsert
|
|
for h in measdata:
|
|
md=measdata[h]
|
|
for m in md['measures']:
|
|
try:
|
|
stime=int(m)
|
|
except:
|
|
print("wrong entry")
|
|
else:
|
|
tsi=tsi+'('+str(m)+','+h+','+str(md['measures'][m])+'),'
|
|
tsi=tsi[:-1]+';'
|
|
try:
|
|
mydb=pymysql.connect(read_default_file="~/.my.cnf",database="rasolar")
|
|
except:
|
|
print("could not connect to mysql")
|
|
with open("missed.sql","a") as sqlstore:
|
|
sqlstore.write(tsi)
|
|
else:
|
|
mycursor=mydb.cursor(pymysql.cursors.DictCursor)
|
|
for h in measdata:
|
|
mycursor.execute('select id from ids where id='+h+';')
|
|
t=mycursor.fetchall()
|
|
if len(t)==0:
|
|
hsql='insert into ids (id,device,varname,sensor,sensorsub,i2c) values ('+h+','
|
|
hm=measdata[h]
|
|
ht={}
|
|
for i in ['device','varname','sensor','sensorsub']:
|
|
if i in hm:
|
|
hsql=hsql+"'"+hm[i]+"'"+','
|
|
else:
|
|
hsql=hsql+"\'\',"
|
|
if 'i2c' in hm:
|
|
try:
|
|
hsql=hsql+"'"+str(hm['i2c'])+"'"
|
|
except:
|
|
hsql=hsql+"'0'"
|
|
else:
|
|
hsql=hsql+0
|
|
hsql=hsql+');'
|
|
try:
|
|
mycursor.execute(hsql)
|
|
except:
|
|
print("could not insert new var_id")
|
|
print(hsql)
|
|
mycursor.execute(tsi)
|
|
mycursor.close()
|
|
mydb.commit()
|
|
mydb.close()
|
|
# print(tsi)
|
|
# print(measdata)
|
|
|
|
|
|
|
|
app=Bottle()
|
|
#bottlesqp=bottle_mysql.Plugin(read_default_file='~/.my.cnf',db="rasolar")
|
|
#app.install(plugin)
|
|
|
|
@app.get('/')
|
|
def approot():
|
|
return '''
|
|
<a href="/haus">Dateneingabe Haus</a></br>
|
|
<a href="/kfz">Dateneingabe KFZ</a></br>
|
|
'''
|
|
|
|
@app.get('/haus')
|
|
def haus():
|
|
return '''
|
|
<form action="/haus" method="post">
|
|
epoch: <input name="epoch" type="text" value=
|
|
wasser: <input name="wasser" type="text" /></br>
|
|
gas: <input name="gas" type="text" /></br>
|
|
Strom: <input name="kwh_haus" type="text" /></br>
|
|
Strom Herd: <input name="kwh_herd" type="text" /></br>
|
|
<input value="Senden" type="submit" />
|
|
</form>
|
|
'''
|
|
|
|
@app.post('/haus')
|
|
def submit_haus():
|
|
indata={}
|
|
for x in payload_hauf:
|
|
indata[x]=request.forms.get(x)
|
|
print(indata)
|
|
|
|
@app.get('/kfz')
|
|
def kfz():
|
|
return '''
|
|
<form action="/kfz" method="post">
|
|
epoch: <input name="epoch" type="text" value=
|
|
km-Stand: <input name="km" type="text" /></br>
|
|
Volumen: <input name="volumen" type="text" /></br>
|
|
Preis: <input name="preis" type="text" /></br>
|
|
<input value="Senden" type="submit" />
|
|
</form>
|
|
'''
|
|
|
|
@app.post('/kfz')
|
|
def submit_kfz():
|
|
indata={}
|
|
for x in payload_kfz:
|
|
indata[x]=request.forms.get(x)
|
|
print(indata)
|
|
|
|
@app.get('/ids')
|
|
def show_ids():
|
|
mydb=pymysql.connect(read_default_file="~/.my.cnf",database="rasolar")
|
|
mycursor=mydb.cursor(pymysql.cursors.DictCursor)
|
|
mycursor.execute('select gm.*,measures.value,ids.varname,ids.device,ids.sensor,ids.i2c,ids.sensorsub from (select id, max(time) as time,count(time) as count from measures group by id) gm join measures on measures.id=gm.id and measures.time=gm.time join ids on ids.id=gm.id where gm.time>= ((select max(time) from measures)-24*6400000);')
|
|
row=mycursor.fetchall()
|
|
mycursor.close()
|
|
mydb.close()
|
|
return template('ids.tpl',measdata=row)
|
|
|
|
@app.get('/cpu')
|
|
def show_ids():
|
|
mydb=pymysql.connect(read_default_file="~/.my.cnf",database="rasolar")
|
|
mycursor=mydb.cursor(pymysql.cursors.DictCursor)
|
|
mycursor.execute('select * from ids where sensor="CPU";')
|
|
channels=mycursor.fetchall()
|
|
cpu_col=cm.rainbow(numpy.linspace(0,1,len(channels)))
|
|
plt.figure(figsize=[6,8])
|
|
for j in range(len(channels)):
|
|
svg_x=[]
|
|
svg_y=[]
|
|
mycursor.execute('select (measures.time-(select min(time) from measures))/1000 as time,measures.value/1000 as value,ids.varname,ids.device,ids.sensor,ids.i2c,ids.sensorsub from measures join ids on ids.id=measures.id where measures.time>= ((select max(time) from measures)-24*6400000) and ids.sensor="CPU" and ids.id='+str(channels[j]['id'])+';')
|
|
row=mycursor.fetchall()
|
|
for i in row:
|
|
svg_x.append(float(i['time']))
|
|
svg_y.append(float(i['value']))
|
|
plt.scatter(svg_x,svg_y,color=cpu_col[j],label=channels[j]['varname']+'; '+channels[j]['device'])
|
|
# plt.legend(loc='upper center',bbox_to_anchor=(0.5,-0.05), shadow=True, ncol=len(channels))
|
|
plt.legend()
|
|
plt.title('CPU Verlauf')
|
|
plt.savefig("cpu.svg")
|
|
mycursor.close()
|
|
mydb.close()
|
|
if len(row)>0:
|
|
return template('cputemp.tpl',measdata=row)
|
|
|
|
@app.get('/svg/<svgfile>')
|
|
def show_svg(svgfile):
|
|
return static_file(svgfile,root=abspath)
|
|
|
|
@app.get('/graph/<mid>')
|
|
def show_graph(mid):
|
|
mydb=pymysql.connect(read_default_file="~/.my.cnf",database="rasolar")
|
|
mycursor=mydb.cursor(pymysql.cursors.DictCursor)
|
|
mycursor.execute('select (measures.time-(select min(time) from measures))/1000 as time,measures.value/1000 as value from measures where id='+str(mid)+';')
|
|
row=mycursor.fetchall()
|
|
mycursor.close()
|
|
mydb.close()
|
|
plt.figure(figsize=[6,8])
|
|
svg_x=[]
|
|
svg_y=[]
|
|
for i in row:
|
|
svg_x.append(float(i['time']))
|
|
svg_y.append(float(i['value']))
|
|
plt.scatter(svg_x,svg_y)
|
|
plt.savefig(mid+".svg")
|
|
if len(row)>0:
|
|
return template('verlauf.tpl',measdata=row,mid=mid)
|
|
|
|
|
|
@app.post('/data/<hash_id>')
|
|
def dataimport(hash_id):
|
|
# print(hash_id)
|
|
timestart=time.time()
|
|
# check if request comes from allowed ip
|
|
if (request.remote_addr in clientlist):
|
|
# hash must be the used gpg key id
|
|
if (hash_id in clientlist[request.remote_addr]):
|
|
# print("correct id")
|
|
# check, if json is transmitted
|
|
try:
|
|
json_in=json.loads(request.json)
|
|
# print(json_in)
|
|
except:
|
|
print("no json")
|
|
else:
|
|
print(time.time()-timestart)
|
|
_thread.start_new_thread(analyse_jsonin,(json_in,hash_id,))
|
|
else:
|
|
print("wrong id")
|
|
else:
|
|
print("not allowed client address")
|
|
|
|
|
|
|
|
run(app,host="",port=8081)
|