import os import sys import yaml import requests import shutil from datetime import date import csv import urllib2 import re import datetime from shutil import copyfile from time import gmtime, strftime import time import calendar import tornado.escape import tornado.ioloop import tornado.web import tornado.autoreload from tornado.escape import json_decode from tornado.escape import json_encode from threading import Timer import collections root = os.path.dirname(__file__) with open("config.yaml", 'r') as stream: try: #print(yaml.load(stream)) config = yaml.load(stream) except yaml.YAMLError as exc: print(exc) if config == None: print("Error: Empty configuration file.") sys.exit(1) class RepeatedTimer(object): def __init__(self, interval, function, *args, **kwargs): self._timer = None self.interval = interval self.function = function self.args = args self.kwargs = kwargs self.is_running = False self.start() def _run(self): self.is_running = False self.start() self.function(*self.args, **self.kwargs) def start(self): if not self.is_running: self._timer = Timer(self.interval, self._run) self._timer.start() self.is_running = True def stop(self): self._timer.cancel() self.is_running = False def setInterval(self, interval): self.interval = interval months = { 'Jan' : 1, 'Feb' : 2, 'Mar' : 3, 'Apr' : 4, 'May' : 5, 'Jun' : 6, 'Jul' : 7, 'Aug' : 8, 'Sep' : 9, 'Oct' : 10, 'Nov' : 11, 'Dec' : 12 } def fetchDataADEI(): with open("varname.yaml", 'r') as stream: try: #print(yaml.load(stream)) varname = yaml.load(stream) except yaml.YAMLError as exc: print(exc) if varname == None: print("Error: Empty varname file.") return cache_data = {} curtime = int(time.time()) #time_range = str((curtime-3600)) + "-" + str(curtime) #time_range = str((curtime-1800)) + "-" + str(curtime) time_range = "-1" for param in varname: #print param dest = config['server'] + config['script'] #url = dest + "?" + varname[param] + "&window=-1" url = dest + "?" + varname[param] + "&window=" + time_range #print url #print config['username'], config['password'] data = requests.get(url, auth=(config['username'], config['password'])).content #tmp_data = data.content #print data # Date/Time, p_string2 # 11-Aug-17 14:49:32.446682, 0.495 lines = data.splitlines() if len(lines) < 2: print "No data:" print "URL: " + url print "\n" continue tmp_data = lines[-1] last_value = tmp_data.split(",")[-1].strip() first_value = tmp_data.split(",")[-2].strip() try: #print last_value test_x = float(last_value) except ValueError: last_value = "" #print last_value try: time_buffer = first_value.split("-") time_buffer[1] = str(months[time_buffer[1]]) first_value = "-".join(time_buffer) first_ts = calendar.timegm(datetime.datetime.strptime(first_value, "%d-%m-%y %H:%M:%S.%f").timetuple()) cache_data[param] = {'timestamp': first_ts, 'value': last_value} #current_timestamp = strftime("%Y-%m-%d %H:%M:%S", gmtime()) current_timestamp = strftime("%Y-%m-%d %H:%M:%S") cache_data['time'] = {"value": current_timestamp} except: print "Problem parsing data:" print "URL: " + url print "Data: " + first_value print "\n" with open("/tmp/.tmp.yaml", 'w') as stream_tmp: stream_tmp.write(yaml.dump(cache_data, default_flow_style=False)) src_file = "/tmp/.tmp.yaml" dst_file = "/tmp/cache.yaml" shutil.copy(src_file, dst_file) print "Start torrenting..." # it auto-starts, no need of rt.start() print "Debugging..." # TODO: Turn off for debug rt = RepeatedTimer(int(config["polling"]), fetchDataADEI) class BaseHandler(tornado.web.RequestHandler): def get_current(self): return self.get_secure_cookie("user") class ListHandler(tornado.web.RequestHandler): def get(self): with open("/tmp/cache.yaml", 'r') as stream: try: #print(yaml.load(stream)) response = yaml.load(stream) except yaml.YAMLError as exc: print(exc) if response == None: response = {"error": "No data entry."} print response self.write(response) class StartHandler(tornado.web.RequestHandler): def get(self): print "Start fetchData" rt.start() class StopHandler(tornado.web.RequestHandler): def get(self): print "Stop fetchData" rt.stop() class SetTimerHandler(tornado.web.RequestHandler): def get(self, duration): print "Set interval" rt.setInterval(float(duration)) class DesignerHandler(tornado.web.RequestHandler): @tornado.web.authenticated def get(self): print "In designer mode." with open("/tmp/cache.yaml", 'r') as stream: try: #print(yaml.load(stream)) cache_data = yaml.load(stream) except yaml.YAMLError as exc: print(exc) if cache_data == None: print("Error: Empty cache data file.") return with open("style.yaml", 'r') as stream: try: #print(yaml.load(stream)) style_data = yaml.load(stream) except yaml.YAMLError as exc: print(exc) data = { "cache": cache_data, "style": style_data } self.render('designer.html', data=data) class VersionHandler(tornado.web.RequestHandler): def get(self): response = {'version': '0.0.1', 'last_build': date.today().isoformat()} self.write(response) class BackupHandler(tornado.web.RequestHandler): def post(self): backup_dst = os.getcwd() + "/backup/" fname = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") os.makedirs(backup_dst + fname) copyfile(os.getcwd() + "/varname.yaml", backup_dst + fname + "/varname.yaml") copyfile(os.getcwd() + "/style.yaml", backup_dst + fname + "/style.yaml") #self.write(json.dumps(response)) class SaveHandler(tornado.web.RequestHandler): def post(self): print self.request.body json_obj = json_decode(self.request.body) print('Post data received') with open("style.yaml", 'w') as output: output.write(yaml.safe_dump(json_obj, encoding='utf-8', allow_unicode=True, default_flow_style=False)) response = {"success": "Data entry inserted."} #self.write(json.dumps(response)) class StatusHandler(tornado.web.RequestHandler): def get(self): print "In status mode." with open("style.yaml", 'r') as stream: try: #print(yaml.load(stream)) style_data = yaml.load(stream) except yaml.YAMLError as exc: print(exc) #if style_data == None: # print("Error: Empty style data file.") # return with open("varname.yaml", 'r') as vstream: try: #print(yaml.load(stream)) varname_data = yaml.load(vstream) except yaml.YAMLError as exc: print(exc) #if varname_data == None: # print("Error: Empty varname data file.") # return data = { #"style": style_data, "varname": varname_data } #if "background" in config: # data["background"] = config["background"] if "title" in config: data["title"] = config["title"] else: data["title"] = "BORA" self.render('index.html', data=data) class AdeiKatrinHandler(tornado.web.RequestHandler): def get(self, **params): #print params sensor_name = str(params["sensor_name"]) """ {'db_group': u'320_KRY_Kryo_4K_CurLead', 'db_name': u'ControlSystem_CPS', 'sensor_name': u'320-RTP-8-1103', 'db_server': u'cscps', 'control_group': u'320_KRY_Kryo_3K'} """ if config["type"] != "adei": print("Error: Wrong handler.") return dest = config['server'] + config['script'] query_cmds = [] query_cmds.append("db_server="+str(params['db_server'])) query_cmds.append("db_name="+str(params['db_name'])) query_cmds.append("db_group="+str(params['db_group'])) query_cmds.append("db_mask=all") query_cmds.append("window=-1") query = "&".join(query_cmds) url = dest + "?" + query #print url # get the db_masks # store the query command in varname data = requests.get(url, auth=(config['username'], config['password'])) cr = data.content cr = cr.split(",") #print cr, len(cr) # handling the inconsistency on naming convention match_token = params['sensor_name'] if params["db_server"] != "lara": # parameter name stored in ADEI with '-IST_Val' suffix if "MOD" in params['sensor_name']: match_token = params['sensor_name'] + "-MODUS_Val" elif "GRA" in params['sensor_name']: match_token = params['sensor_name'] + "-GRAD_Val" elif "RPO" in params['sensor_name']: match_token = params['sensor_name'] + "-ZUST_Val" elif "VYS" in params['sensor_name']: match_token = params['sensor_name'] + "-ZUST_Val" else: match_token = params['sensor_name'] + "-IST_Val" db_mask = None for i, item in enumerate(cr): if "[" and "]" in item.strip(): lhs = re.match(r"[^[]*\[([^]]*)\]", item.strip()).groups()[0] if lhs == params['sensor_name']: db_mask = i - 1 else: if item.strip() == match_token: db_mask = i - 1 if db_mask == None: response = {"Error": "Cannot find variable on ADEI server."} self.write(response) return query_cmds = [] query_cmds.append("db_server="+str(params['db_server'])) query_cmds.append("db_name="+str(params['db_name'])) query_cmds.append("db_group="+str(params['db_group'])) query_cmds.append("db_mask="+str(db_mask)) query = "&".join(query_cmds) # column name available # store in yaml file with open("varname.yaml", 'r') as stream: try: #print(yaml.load(stream)) cache_data = yaml.load(stream) except yaml.YAMLError as exc: print(exc) if cache_data == None: cache_data = {} cache_data[sensor_name] = query else: if sensor_name not in cache_data: cache_data[sensor_name] = query else: response = {"Error": "Variable already available in varname file."} self.write(response) return with open("varname.yaml", 'w') as output: output.write(yaml.dump(cache_data, default_flow_style=False)) response = {"success": "Data entry inserted."} #print match_token, db_mask self.write(response) class GetDataHandler(tornado.web.RequestHandler): def get(self): cache_data = None with open("/tmp/cache.yaml", 'r') as stream: try: #print(yaml.load(stream)) cache_data = yaml.load(stream) except yaml.YAMLError as exc: print(exc) #print("GetData:") if cache_data == None: cache_data = {} #print cache_data self.write(cache_data) class AuthLoginHandler(BaseHandler): def get(self): try: errormessage = self.get_argument("error") except: errormessage = "" print errormessage self.render("login.html", errormessage = errormessage) def check_permission(self, password, username): if username == config["username"] and password == config["pw_designer"]: return True return False def post(self): username = self.get_argument("username", "") password = self.get_argument("password", "") auth = self.check_permission(password, username) if auth: self.set_current_user(username) print "In designer mode." with open("/tmp/cache.yaml", 'r') as stream: try: #print(yaml.load(stream)) cache_data = yaml.load(stream) except yaml.YAMLError as exc: print(exc) #if cache_data == None: # print("Error: Empty cache data file.") # return with open("style.yaml", 'r') as stream: try: #print(yaml.load(stream)) style_data = yaml.load(stream) except yaml.YAMLError as exc: print(exc) if style_data: index_data = list(set(cache_data) | set(style_data)) else: index_data = cache_data print index_data data = { "cache": cache_data, "style": style_data, "index": index_data, } if "background" in config: data["background"] = config["background"] self.render('designer.html', data=data) else: error_msg = u"?error=" + tornado.escape.url_escape("Login incorrect") self.redirect(u"/auth/login/" + error_msg) def set_current_user(self, user): if user: self.set_secure_cookie("user", tornado.escape.json_encode(user)) else: self.clear_cookie("user") application = tornado.web.Application([ (r"/auth/login/?", AuthLoginHandler), (r"/version/?", VersionHandler), (r"/list/?", ListHandler), (r"/start/?", StartHandler), (r"/backup/?", BackupHandler), (r"/stop/?", StopHandler), (r"/designer/?", DesignerHandler), (r"/", StatusHandler), (r"/status/?", StatusHandler), (r"/save/?", SaveHandler), (r"/getdata/?", GetDataHandler), (r"/timer/(?P[^\/]+)/?", SetTimerHandler), (r"/add/(?P[^\/]+)/?(?P[^\/]+)/?(?P[^\/]+)/?(?P[^\/]+)?", AdeiKatrinHandler) ], debug=True, static_path=os.path.join(root, 'static'), js_path=os.path.join(root, 'js'), login_url="/auth/login", cookie_secret='L8LwECiNRxq2N0N2eGxx9MZlrpmuMEimlydNX/vt1LM=') if __name__ == "__main__": application.listen(int(config["port"])) tornado.autoreload.start() #tornado.autoreload.watch('myfile') tornado.ioloop.IOLoop.instance().start()