core.py 14 KB

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