You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 line
5.5KB

  1. import datetime
  2. import os
  3. import time
  4. import requests
  5. import logging
  6. from flask import request, send_from_directory, json
  7. from flask_classy import FlaskView, route
  8. from modules import cbpi
  9. class LogView(FlaskView):
  10. def __init__(self):
  11. self.logger = logging.getLogger(__name__)
  12. @route('/', methods=['GET'])
  13. def get_all_logfiles(self):
  14. result = []
  15. for filename in os.listdir("./logs"):
  16. if filename.endswith(".log"):
  17. result.append(filename)
  18. return json.dumps(result)
  19. @route('/actions')
  20. def actions(self):
  21. filename = "./logs/action.log"
  22. if not os.path.isfile(filename):
  23. self.logger.warn("File does not exist [%s]", filename)
  24. return json.dumps([])
  25. import csv
  26. array = []
  27. with open(filename, 'rb') as f:
  28. reader = csv.reader(f)
  29. for row in reader:
  30. try:
  31. time.mktime(time.strptime(row[0], "%Y-%m-%d %H:%M:%S"))
  32. array.append([int(time.mktime(time.strptime(row[0], "%Y-%m-%d %H:%M:%S")) * 1000), row[1]])
  33. except:
  34. pass
  35. json_dumps = json.dumps(array)
  36. self.logger.debug("Loaded action.log [%s]", json_dumps)
  37. return json_dumps
  38. @route('/<file>', methods=["DELETE"])
  39. def clearlog(self, file):
  40. """
  41. Overload delete method to shutdown sensor before delete
  42. :param id: sensor id
  43. :return: HTTP 204
  44. """
  45. if not self.check_filename(file):
  46. return ('File Not Found', 404)
  47. filename = "./logs/%s" % file
  48. if os.path.isfile(filename) == True:
  49. os.remove(filename)
  50. cbpi.notify("log deleted succesfully", "")
  51. else:
  52. cbpi.notify("Failed to delete log", "", type="danger")
  53. return ('', 204)
  54. def querry_tsdb(self, type, id):
  55. kairosdb_server = "http://192.168.178.20:5001"
  56. data = dict(metrics=[
  57. {
  58. "tags": {},
  59. "name": "%s_%s" % (type, id),
  60. "aggregators": [
  61. {
  62. "name": "avg",
  63. "align_sampling": True,
  64. "sampling": {
  65. "value": "1",
  66. "unit": "minutes"
  67. },
  68. "align_start_time": True
  69. }
  70. ]
  71. }
  72. ],
  73. cache_time=0,
  74. start_relative={
  75. "value": "1",
  76. "unit": "days"
  77. })
  78. response = requests.post(kairosdb_server + "/api/v1/datapoints/query", json.dumps(data))
  79. if response.ok:
  80. self.logger.debug("Fetching time series for [%s_%s] took [%s]", type, id, response.elapsed)
  81. self.logger.debug("Time series for [%s_%s] is [%s]", type, id, response.json())
  82. return response.json()["queries"][0]["results"][0]["values"]
  83. else:
  84. self.logger.warning("Failed to fetch time series for [%s_%s]. Response [%s]", type, id, response)
  85. def read_log_as_json(self, type, id):
  86. return self.querry_tsdb(type, id)
  87. filename = "./logs/%s_%s.log" % (type, id)
  88. if os.path.isfile(filename) == False:
  89. return
  90. import csv
  91. array = []
  92. with open(filename, 'rb') as f:
  93. reader = csv.reader(f)
  94. for row in reader:
  95. try:
  96. array.append([int((datetime.datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S") - datetime.datetime(1970,
  97. 1,
  98. 1)).total_seconds()) * 1000,
  99. float(row[1])])
  100. except:
  101. pass
  102. print(array)
  103. return array
  104. def convert_chart_data_to_json(self, chart_data):
  105. return {"name": chart_data["name"],
  106. "data": self.read_log_as_json(chart_data["data_type"], chart_data["data_id"])}
  107. @route('/<t>/<int:id>', methods=["POST"])
  108. def get_logs_as_json(self, t, id):
  109. data = request.json
  110. result = []
  111. if t == "s":
  112. name = cbpi.cache.get("sensors").get(id).name
  113. result.append({"name": name, "data": self.read_log_as_json("sensor", id)})
  114. if t == "k":
  115. kettle = cbpi.cache.get("kettle").get(id)
  116. result = map(self.convert_chart_data_to_json, cbpi.get_controller(kettle.logic).get("class").chart(kettle))
  117. if t == "f":
  118. fermenter = cbpi.cache.get("fermenter").get(id)
  119. result = map(self.convert_chart_data_to_json,
  120. cbpi.get_fermentation_controller(fermenter.logic).get("class").chart(fermenter))
  121. return json.dumps(result)
  122. @route('/download/<file>')
  123. @cbpi.nocache
  124. def download(self, file):
  125. if not self.check_filename(file):
  126. return ('File Not Found', 404)
  127. return send_from_directory('../logs', file, as_attachment=True, attachment_filename=file)
  128. def check_filename(self, name):
  129. import re
  130. pattern = re.compile('^([A-Za-z0-9-_])+.log$')
  131. return True if pattern.match(name) else False
  132. @cbpi.initalizer()
  133. def init(app):
  134. """
  135. Initializer for the message module
  136. :param app: the flask app
  137. :return: None
  138. """
  139. LogView.register(cbpi.app, route_base='/api/logs')