core.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. import os
  2. import sys
  3. import yaml
  4. import requests
  5. import shutil
  6. from datetime import date
  7. import csv
  8. import urllib2
  9. import re
  10. import datetime
  11. from shutil import copyfile
  12. from time import gmtime, strftime
  13. import time
  14. import tornado.escape
  15. import tornado.ioloop
  16. import tornado.web
  17. import tornado.autoreload
  18. from tornado.escape import json_decode
  19. from tornado.escape import json_encode
  20. from threading import Timer
  21. import collections
  22. root = os.path.dirname(__file__)
  23. with open("config.yaml", 'r') as stream:
  24. try:
  25. #print(yaml.load(stream))
  26. config = yaml.load(stream)
  27. except yaml.YAMLError as exc:
  28. print(exc)
  29. if config == None:
  30. print("Error: Empty configuration file.")
  31. sys.exit(1)
  32. class RepeatedTimer(object):
  33. def __init__(self, interval, function, *args, **kwargs):
  34. self._timer = None
  35. self.interval = interval
  36. self.function = function
  37. self.args = args
  38. self.kwargs = kwargs
  39. self.is_running = False
  40. self.start()
  41. def _run(self):
  42. self.is_running = False
  43. self.start()
  44. self.function(*self.args, **self.kwargs)
  45. def start(self):
  46. if not self.is_running:
  47. self._timer = Timer(self.interval, self._run)
  48. self._timer.start()
  49. self.is_running = True
  50. def stop(self):
  51. self._timer.cancel()
  52. self.is_running = False
  53. def setInterval(self, interval):
  54. self.interval = interval
  55. def fetchDataADEI():
  56. if os.path.isfile(os.getcwd()+"/.mutex"):
  57. #print("Process running...")
  58. return
  59. else:
  60. #print("Created mutex")
  61. file = open(os.getcwd()+'/.mutex', 'w+')
  62. with open("varname.yaml", 'r') as stream:
  63. try:
  64. #print(yaml.load(stream))
  65. varname = yaml.load(stream)
  66. except yaml.YAMLError as exc:
  67. print(exc)
  68. if varname == None:
  69. print("Error: Empty varname file.")
  70. os.remove(os.getcwd()+"/.mutex")
  71. return
  72. cache_data = {}
  73. curtime = int(time.time())
  74. #time_range = str((curtime-3600)) + "-" + str(curtime)
  75. time_range = str((curtime-1800)) + "-" + str(curtime)
  76. for param in varname:
  77. print param
  78. dest = config['server'] + config['script']
  79. #url = dest + "?" + varname[param] + "&window=-1"
  80. url = dest + "?" + varname[param] + "&window=" + time_range
  81. print url
  82. data = requests.get(url,
  83. auth=(config['username'],
  84. config['password'])).content
  85. #tmp_data = data.content
  86. #print "CHECK THIS"
  87. #print data
  88. last_value = data.split(",")[-1].strip()
  89. try:
  90. print last_value
  91. test_x = float(last_value)
  92. except ValueError:
  93. last_value = ""
  94. print last_value
  95. cache_data[param] = last_value
  96. #current_timestamp = strftime("%Y-%m-%d %H:%M:%S", gmtime())
  97. current_timestamp = strftime("%Y-%m-%d %H:%M:%S")
  98. cache_data['time'] = current_timestamp
  99. with open(".tmp.yaml", 'w') as stream_tmp:
  100. stream_tmp.write(yaml.dump(cache_data, default_flow_style=False))
  101. src_file = os.getcwd() + "/.tmp.yaml"
  102. dst_file = os.getcwd() + "/cache.yaml"
  103. shutil.copy(src_file, dst_file)
  104. os.remove(os.getcwd()+"/.mutex")
  105. print "Start torrenting..."
  106. # it auto-starts, no need of rt.start()
  107. print "Debugging..."
  108. # TODO: Turn off for debug
  109. rt = RepeatedTimer(int(config["polling"]), fetchDataADEI)
  110. class BaseHandler(tornado.web.RequestHandler):
  111. def get_current(self):
  112. return self.get_secure_cookie("user")
  113. class ListHandler(tornado.web.RequestHandler):
  114. def get(self):
  115. with open("cache.yaml", 'r') as stream:
  116. try:
  117. #print(yaml.load(stream))
  118. response = yaml.load(stream)
  119. except yaml.YAMLError as exc:
  120. print(exc)
  121. if response == None:
  122. response = {"error": "No data entry."}
  123. print response
  124. self.write(response)
  125. class StartHandler(tornado.web.RequestHandler):
  126. def get(self):
  127. print "Start fetchData"
  128. rt.start()
  129. class StopHandler(tornado.web.RequestHandler):
  130. def get(self):
  131. print "Stop fetchData"
  132. rt.stop()
  133. if os.path.isfile(os.getcwd()+"/.mutex"):
  134. os.remove(os.getcwd()+"/.mutex")
  135. class SetTimerHandler(tornado.web.RequestHandler):
  136. def get(self, duration):
  137. print "Set interval"
  138. rt.setInterval(float(duration))
  139. class DesignerHandler(tornado.web.RequestHandler):
  140. @tornado.web.authenticated
  141. def get(self):
  142. print "In designer mode."
  143. with open("cache.yaml", 'r') as stream:
  144. try:
  145. #print(yaml.load(stream))
  146. cache_data = yaml.load(stream)
  147. except yaml.YAMLError as exc:
  148. print(exc)
  149. if cache_data == None:
  150. print("Error: Empty cache data file.")
  151. return
  152. with open("style.yaml", 'r') as stream:
  153. try:
  154. #print(yaml.load(stream))
  155. style_data = yaml.load(stream)
  156. except yaml.YAMLError as exc:
  157. print(exc)
  158. data = {
  159. "cache": cache_data,
  160. "style": style_data
  161. }
  162. self.render('designer.html', data=data)
  163. class VersionHandler(tornado.web.RequestHandler):
  164. def get(self):
  165. response = {'version': '0.0.1',
  166. 'last_build': date.today().isoformat()}
  167. self.write(response)
  168. class BackupHandler(tornado.web.RequestHandler):
  169. def post(self):
  170. backup_dst = os.getcwd() + "/backup/"
  171. fname = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
  172. os.makedirs(backup_dst + fname)
  173. copyfile(os.getcwd() + "/varname.yaml", backup_dst + fname + "/varname.yaml")
  174. copyfile(os.getcwd() + "/style.yaml", backup_dst + fname + "/style.yaml")
  175. #self.write(json.dumps(response))
  176. class SaveHandler(tornado.web.RequestHandler):
  177. def post(self):
  178. print self.request.body
  179. json_obj = json_decode(self.request.body)
  180. print('Post data received')
  181. with open("style.yaml", 'w') as output:
  182. output.write(yaml.safe_dump(json_obj, encoding='utf-8', allow_unicode=True, default_flow_style=False))
  183. response = {"success": "Data entry inserted."}
  184. #self.write(json.dumps(response))
  185. class StatusHandler(tornado.web.RequestHandler):
  186. def get(self):
  187. print "In status mode."
  188. with open("style.yaml", 'r') as stream:
  189. try:
  190. #print(yaml.load(stream))
  191. style_data = yaml.load(stream)
  192. except yaml.YAMLError as exc:
  193. print(exc)
  194. #if style_data == None:
  195. # print("Error: Empty style data file.")
  196. # return
  197. with open("varname.yaml", 'r') as vstream:
  198. try:
  199. #print(yaml.load(stream))
  200. varname_data = yaml.load(vstream)
  201. except yaml.YAMLError as exc:
  202. print(exc)
  203. #if varname_data == None:
  204. # print("Error: Empty varname data file.")
  205. # return
  206. data = {
  207. #"style": style_data,
  208. "varname": varname_data
  209. }
  210. #if "background" in config:
  211. # data["background"] = config["background"]
  212. if "title" in config:
  213. data["title"] = config["title"]
  214. else:
  215. data["title"] = "BORA"
  216. self.render('index.html', data=data)
  217. class AdeiKatrinHandler(tornado.web.RequestHandler):
  218. def get(self, **params):
  219. #print params
  220. sensor_name = str(params["sensor_name"])
  221. """
  222. {'db_group': u'320_KRY_Kryo_4K_CurLead',
  223. 'db_name': u'ControlSystem_CPS',
  224. 'sensor_name': u'320-RTP-8-1103',
  225. 'db_server': u'cscps',
  226. 'control_group': u'320_KRY_Kryo_3K'}
  227. """
  228. if config["type"] != "adei":
  229. print("Error: Wrong handler.")
  230. return
  231. dest = config['server'] + config['script']
  232. query_cmds = []
  233. query_cmds.append("db_server="+str(params['db_server']))
  234. query_cmds.append("db_name="+str(params['db_name']))
  235. query_cmds.append("db_group="+str(params['db_group']))
  236. query_cmds.append("db_mask=all")
  237. query_cmds.append("window=-1")
  238. query = "&".join(query_cmds)
  239. url = dest + "?" + query
  240. #print url
  241. # get the db_masks
  242. # store the query command in varname
  243. data = requests.get(url, auth=(config['username'], config['password']))
  244. cr = data.content
  245. cr = cr.split(",")
  246. print cr, len(cr)
  247. # handling the inconsistency on naming convention
  248. match_token = params['sensor_name']
  249. if params["db_server"] != "lara":
  250. # parameter name stored in ADEI with '-IST_Val' suffix
  251. if "MOD" in params['sensor_name']:
  252. match_token = params['sensor_name'] + "-MODUS_Val"
  253. elif "GRA" in params['sensor_name']:
  254. match_token = params['sensor_name'] + "-GRAD_Val"
  255. elif "RPO" in params['sensor_name']:
  256. match_token = params['sensor_name'] + "-ZUST_Val"
  257. elif "VYS" in params['sensor_name']:
  258. match_token = params['sensor_name'] + "-ZUST_Val"
  259. else:
  260. match_token = params['sensor_name'] + "-IST_Val"
  261. db_mask = None
  262. for i, item in enumerate(cr):
  263. if "[" and "]" in item.strip():
  264. lhs = re.match(r"[^[]*\[([^]]*)\]", item.strip()).groups()[0]
  265. if lhs == params['sensor_name']:
  266. db_mask = i - 1
  267. else:
  268. if item.strip() == match_token:
  269. db_mask = i - 1
  270. if db_mask == None:
  271. response = {"Error": "Cannot find variable on ADEI server."}
  272. self.write(response)
  273. return
  274. query_cmds = []
  275. query_cmds.append("db_server="+str(params['db_server']))
  276. query_cmds.append("db_name="+str(params['db_name']))
  277. query_cmds.append("db_group="+str(params['db_group']))
  278. query_cmds.append("db_mask="+str(db_mask))
  279. query = "&".join(query_cmds)
  280. # column name available
  281. # store in yaml file
  282. with open("varname.yaml", 'r') as stream:
  283. try:
  284. #print(yaml.load(stream))
  285. cache_data = yaml.load(stream)
  286. except yaml.YAMLError as exc:
  287. print(exc)
  288. if cache_data == None:
  289. cache_data = {}
  290. cache_data[sensor_name] = query
  291. else:
  292. if sensor_name not in cache_data:
  293. cache_data[sensor_name] = query
  294. else:
  295. response = {"Error": "Variable already available in varname file."}
  296. self.write(response)
  297. return
  298. with open("varname.yaml", 'w') as output:
  299. output.write(yaml.dump(cache_data, default_flow_style=False))
  300. response = {"success": "Data entry inserted."}
  301. #print match_token, db_mask
  302. self.write(response)
  303. class GetDataHandler(tornado.web.RequestHandler):
  304. def get(self):
  305. with open("cache.yaml", 'r') as stream:
  306. try:
  307. #print(yaml.load(stream))
  308. cache_data = yaml.load(stream)
  309. except yaml.YAMLError as exc:
  310. print(exc)
  311. print("GetData:")
  312. if cache_data == None:
  313. cache_data = {}
  314. print cache_data
  315. self.write(cache_data)
  316. class AuthLoginHandler(BaseHandler):
  317. def get(self):
  318. try:
  319. errormessage = self.get_argument("error")
  320. except:
  321. errormessage = ""
  322. print errormessage
  323. self.render("login.html", errormessage = errormessage)
  324. def check_permission(self, password, username):
  325. if username == config["username"] and password == config["pw_designer"]:
  326. return True
  327. return False
  328. def post(self):
  329. username = self.get_argument("username", "")
  330. password = self.get_argument("password", "")
  331. auth = self.check_permission(password, username)
  332. if auth:
  333. self.set_current_user(username)
  334. print "In designer mode."
  335. with open("cache.yaml", 'r') as stream:
  336. try:
  337. #print(yaml.load(stream))
  338. cache_data = yaml.load(stream)
  339. except yaml.YAMLError as exc:
  340. print(exc)
  341. #if cache_data == None:
  342. # print("Error: Empty cache data file.")
  343. # return
  344. with open("style.yaml", 'r') as stream:
  345. try:
  346. #print(yaml.load(stream))
  347. style_data = yaml.load(stream)
  348. except yaml.YAMLError as exc:
  349. print(exc)
  350. if style_data:
  351. index_data = list(set(cache_data) | set(style_data))
  352. else:
  353. index_data = cache_data
  354. print index_data
  355. data = {
  356. "cache": cache_data,
  357. "style": style_data,
  358. "index": index_data,
  359. }
  360. if "background" in config:
  361. data["background"] = config["background"]
  362. self.render('designer.html', data=data)
  363. else:
  364. error_msg = u"?error=" + tornado.escape.url_escape("Login incorrect")
  365. self.redirect(u"/auth/login/" + error_msg)
  366. def set_current_user(self, user):
  367. if user:
  368. self.set_secure_cookie("user", tornado.escape.json_encode(user))
  369. else:
  370. self.clear_cookie("user")
  371. application = tornado.web.Application([
  372. (r"/auth/login/?", AuthLoginHandler),
  373. (r"/version/?", VersionHandler),
  374. (r"/list/?", ListHandler),
  375. (r"/start/?", StartHandler),
  376. (r"/backup/?", BackupHandler),
  377. (r"/stop/?", StopHandler),
  378. (r"/designer/?", DesignerHandler),
  379. (r"/status/?", StatusHandler),
  380. (r"/save/?", SaveHandler),
  381. (r"/getdata/?", GetDataHandler),
  382. (r"/timer/(?P<duration>[^\/]+)/?", SetTimerHandler),
  383. (r"/add/(?P<db_server>[^\/]+)/?(?P<db_name>[^\/]+)/?(?P<db_group>[^\/]+)/?(?P<sensor_name>[^\/]+)?", AdeiKatrinHandler)
  384. ], debug=True, static_path=os.path.join(root, 'static'), js_path=os.path.join(root, 'js'), login_url="/auth/login", cookie_secret='L8LwECiNRxq2N0N2eGxx9MZlrpmuMEimlydNX/vt1LM=')
  385. if __name__ == "__main__":
  386. application.listen(int(config["port"]))
  387. tornado.autoreload.start()
  388. #tornado.autoreload.watch('myfile')
  389. tornado.ioloop.IOLoop.instance().start()