#!/usr/bin/env python3 from bottle import get,post,request,Bottle,run,template import threading,time,json,zlib,gnupg,socket,psutil,os,sys,requests,uuid from queue import Queue payload_haus=["wasser","gas","kwh_haus","kwh_herd"] payload_kfz=["km","volumen","preis"] macadress=str(hex(uuid.getnode()))[2:-1] 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() sensors={ "bme280":{"enable":0,"script":"log_bme280.py","running":0}, "tristar":{"enable":0,"script":"log_tristar.py","running":0}, "vedirect":{"enable":0,"script":"log_vedirect.py","running":0}, "mcp9808": {"enable":0,"script":"log_mcp9808.py","running":0}, "tsl2591":{"enable":0,"script":"log_tsl2591.py","running":0}, "veml6070":{"enable":0,"script":"log_veml6070.py","running":0}, "w1therm":{"enable":0,"script":"log_w1.py","running":0}, "ads1x15":{"enable":0,"script":"log_ads1x15.py","running":0} } parameter={"device":socket.gethostname(),"allowed_ip":{"127.0.0.1":"25A4CF79414F10FD"},"gpg_keyid":"25A4CF79414F10FD","server_transfer_wait":2,"server_keyid":"25A4CF79414F10FD"} for n in parameter: if n in log_conf: parameter[n]=log_conf[n] for sns in sensors: if sns in log_conf: if 'enable' in log_conf[sns]: if log_conf[sns]['enable'] == 1: sensors[sns]['enable']=1 if "sqlserver" in log_conf: hostname="localhost" if "host" in log_conf['sqlserver']: hostname=log_conf['sqlserver']['host'] port=8081 # if "port" in log_conf['sqlserver']: # port=int(log_conf['sqlserver']['port']) gpg=gnupg.GPG('/usr/bin/gpg') try: gpgkey=gpg.list_keys(keys=parameter['gpg_keyid'])[0] except: gpgkey=[] try: servergpgkey=gpg.list_keys(keys=parameter['server_keyid'])[0] except: servergpgkey=[] measdata={} count_tickets=0 last_ticket_time=0 _HASH="hash" _SIGNEDGPG="signed_gpg" _PAYLOAD="payload" _MEASURES="measures" _BEGINSIGNATURE="-----BEGIN PGP SIGNATURE-----" _BEGINMESSAGE="-----BEGIN PGP SIGNED MESSAGE-----" _BEGINHASH="Hash:" def sql_insert(q): count_tickets=0 measdata={} server_last_transmit=0 while True: if q.empty(): time.sleep(0.1) # print("ping"+str(time.time())) if (time.time()-server_last_transmit)>parameter['server_transfer_wait']: if len(measdata)==0: server_last_transmit=time.time()-parameter['server_transfer_wait']/2 else: json_out={"data":measdata} if ('fingerprint' in servergpgkey) and ('fingerprint' in gpgkey): json_out={"encrypted_data":gpg.encrypt(json.dumps(measdata),servergpgkey['fingerprint'],sign=gpgkey['fingerprint']).data.decode("utf-8")} if ('fingerprint' not in servergpgkey) and ('fingerprint' in gpgkey): json_out={"signed_data":gpg.sign(json.dumps(measdata),keyid=gpgkey['keyid']).data.decode("utf-8")} print("http://"+hostname+":"+str(port)+"/data/"+gpgkey['keyid']) try: _r=requests.post("http://"+hostname+":"+str(port)+"/data/"+gpgkey['keyid'],json=json.dumps(json_out)) except: _r={"status_code":404} print("could not send to server") # print(json.dumps(json_out)) server_last_transmit=time.time()-parameter['server_transfer_wait']/2 else: if _r.status_code==200: measdata={} server_last_transmit=time.time() print(str(count_tickets)+" tickets send") count_tickets=0 else: print("could not send to server") print(_r.status_code) server_last_transmit=time.time()-parameter['server_transfer_wait']/2 else: try: indata=q.get() if indata is not None: q.task_done() except Exception as e: print("Error during queuing") print(e) else: count_tickets=count_tickets+1 if indata['hash'] in measdata: for i in indata['payload']['measures']: measdata[indata['hash']]['measures'][i]=indata['payload']['measures'][i] else: measdata[indata['hash']]=indata['payload'] app=Bottle() @app.get('/') def approot(): sensor_list=[] for p in psutil.process_iter(): if p.name() == 'python3': sensor_list.append(p.cmdline()[1].split('/')[-1]) for sns in sensors: print(sns) if sensors[sns]['enable']==1: print(sensors[sns]['script']) sensors[sns]['running']= sensors[sns]['script'] in sensor_list return template('main.tpl',server=socket.gethostname(),cpupercent=psutil.cpu_percent(),countticket=count_tickets,tickettime=last_ticket_time,measdata=measdata,sensors=sensors) @app.post('/') def submit_root(): sensor_start=request.forms.get('sensor') if sensor_start in sensors: sensor_script=abspath+'/'+sensors[sensor_start]['script'] try: stored_timestamps=os.path.getsize(sensor_script) except: print("start script does not exist") else: os.spawnl(os.P_NOWAIT,sensor_script,' ') @app.post('/data/') def dataimport(hash_id): # print(hash_id) timestart=time.time() # check if request comes from allowed ip if request.remote_addr in parameter['allowed_ip']: # check, if json is transmitted try: json_in=json.loads(request.json) # print(json_in) except: print("no json") else: if _HASH in json_in: if int(json_in[_HASH]) == hash_id: bcorrect=False if _PAYLOAD in json_in: if _MEASURES in json_in[_PAYLOAD]: print("unsigned "+str(time.time()-timestart)) q.put(json_in,block=False) bcorrect=True if _SIGNEDGPG in json_in: # check if signature of data is correct and key is allowed for ip vgpg=gpg.verify(json_in[_SIGNEDGPG]) print(time.time()-timestart) if vgpg.valid and vgpg.key_id in parameter['allowed_ip'][request.remote_addr]: signed_in=json_in[_SIGNEDGPG].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: last_ticket_time=time.time()-timestart print(last_ticket_time) q.put(json.loads(signed_in[0]),block=False) else: print("malformed signed packet") print(json_in) else: print("could not verify gpg signature") print(json_in) else: print("wrong id") else: print("json has no hash field") print(json_in) else: print("not allowed client address") @app.get('/haus') def haus(): return template('''
epoch:
wasser:
gas:
Strom:
Strom Herd:
''',td=str(int(1000*time.time()))) @app.post('/haus') def submit_haus(): indata={} json_out={} xhash=macadress+'banana'+str(0)+'hand' ts=request.forms.get('epoch') for x in payload_haus: idstring=macadress+'banana'+str(0)+'hand'+x xhash=zlib.crc32(idstring.encode("utf-8")) % (1<<32) json_out[xhash]={"hash":xhash,"signature":"","payload":{"device":"banana","varname":x,"i2c":0,"sensor":"manuell","mac":macadress,"measures":{ts:request.forms.get(x)}}} q.put({"hash":xhash,"signature":"","payload":{"device":"banana","varname":x,"i2c":0,"sensor":"manuell","mac":macadress,"measures":{ts:request.forms.get(x)}}},block=False) print(indata) @app.get('/kfz') def kfz(): return template('''
epoch:
km-Stand:
Volumen:
Preis:
''',td=str(int(1000*time.time()))) @app.post('/kfz') def submit_kfz(): indata={} json_out={} xhash=macadress+'banana'+str(0)+'hand' ts=request.forms.get('epoch') for x in payload_kfz: idstring=macadress+'banana'+str(0)+'hand'+x xhash=zlib.crc32(idstring.encode("utf-8")) % (1<<32) json_out[xhash]={"hash":xhash,"signature":"","payload":{"device":"banana","varname":x,"i2c":0,"sensor":"manuell","mac":macadress,"measures":{ts:request.forms.get(x)}}} q.put({"hash":xhash,"signature":"","payload":{"device":"banana","varname":x,"i2c":0,"sensor":"manuell","mac":macadress,"measures":{ts:request.forms.get(x)}}},block=False) print(json_out) # q.put(json_out,block=False) @app.get('/test') def get_test(): return template('''



''') @app.post('/test') def submit_test(): print(request.forms.get('but')) q=Queue(maxsize=0) sql_worker=threading.Thread(target=sql_insert,args=(q,)) sql_worker.setDaemon(True) sql_worker.start() run(app,host="",port=8080)