Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

270 строки
8.9KB

  1. import logging
  2. import time
  3. from flask import request
  4. from flask_classy import route
  5. from modules.core.core import cbpi
  6. from modules.core.db import get_db, DBModel
  7. from modules.core.baseview import BaseView
  8. from modules.database.dbmodel import Fermenter, FermenterStep
  9. class FermenterView(BaseView):
  10. model = Fermenter
  11. cache_key = "fermenter"
  12. def __init__(self):
  13. self.logger = logging.getLogger(__name__)
  14. def _post_post_callback(self, m):
  15. m.state = False
  16. m.steps = []
  17. def _pre_put_callback(self, m):
  18. m.state = False
  19. try:
  20. m.instance.stop()
  21. except:
  22. pass
  23. def _post_put_callback(self, m):
  24. m.state = False
  25. @route('/<int:id>/targettemp/<temp>', methods=['POST'])
  26. def postTargetTemp(self, id, temp):
  27. if temp is None or not temp:
  28. return ('', 500)
  29. id = int(id)
  30. temp = float(temp)
  31. cbpi.cache.get(self.cache_key)[id].target_temp = float(temp)
  32. self.model.update(**self.api.cache.get(self.cache_key)[id].__dict__)
  33. cbpi.ws_emit("UPDATE_FERMENTER_TARGET_TEMP", {"id": id, "target_temp": temp})
  34. return ('', 204)
  35. @route('/<int:id>/brewname', methods=['POST'])
  36. def postBrewName(self, id):
  37. data = request.json
  38. brewname = data.get("brewname")
  39. cbpi.cache.get(self.cache_key)[id].brewname = brewname
  40. self.model.update(**self.api.cache.get(self.cache_key)[id].__dict__)
  41. cbpi.ws_emit("UPDATE_FERMENTER_BREWNAME", {"id": id, "brewname": brewname})
  42. return ('', 204)
  43. @classmethod
  44. def post_init_callback(cls, obj):
  45. obj.steps = FermenterStep.get_by_fermenter_id(obj.id)
  46. obj.state = False
  47. @route('/<int:id>/step', methods=['POST'])
  48. def postStep(self, id):
  49. data = request.json
  50. order_max = FermenterStep.get_max_order(id)
  51. order = order_max + 1 if order_max is not None else 1
  52. data["order"] = order
  53. data["days"] = 0 if data["days"] == "" else data["days"]
  54. data["hours"] = 0 if data["hours"] == "" else data["hours"]
  55. data["minutes"] = 0 if data["minutes"] == "" else data["minutes"]
  56. data["temp"] = 0 if data["temp"] == "" else data["temp"]
  57. data["state"] = "I"
  58. data["name"] = "NO NAME" if data["name"] == "" else data["name"]
  59. f = FermenterStep.insert(**data)
  60. cbpi.cache.get(self.cache_key)[id].steps.append(f)
  61. cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
  62. return ('', 204)
  63. @route('/<int:id>/step/<int:stepid>', methods=["PUT"])
  64. def putStep(self, id, stepid):
  65. data = request.json
  66. # Select modal
  67. data["id"] = stepid
  68. data["fermenter_id"] = id
  69. data["days"] = 0 if data["days"] == "" else data["days"]
  70. data["hours"] = 0 if data["hours"] == "" else data["hours"]
  71. data["minutes"] = 0 if data["minutes"] == "" else data["minutes"]
  72. for s in cbpi.cache.get(self.cache_key)[id].steps:
  73. if s.id == stepid:
  74. s.__dict__.update(**data)
  75. FermenterStep.update(**s.__dict__)
  76. break
  77. cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
  78. return ('', 204)
  79. @route('/<int:id>/step/<int:stepid>', methods=["DELETE"])
  80. def deleteStep(self, id, stepid):
  81. for idx, s in enumerate(cbpi.cache.get(self.cache_key)[id].steps):
  82. if s.id == stepid:
  83. del cbpi.cache.get(self.cache_key)[id].steps[idx]
  84. FermenterStep.delete(s.id)
  85. break
  86. cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
  87. return ('', 204)
  88. @route('/<int:id>/start', methods=['POST'])
  89. def start_fermentation(self, id):
  90. active = None
  91. for idx, s in enumerate(cbpi.cache.get(self.cache_key)[id].steps):
  92. if s.state == 'A':
  93. active = s
  94. break
  95. inactive = None
  96. for idx, s in enumerate(cbpi.cache.get(self.cache_key)[id].steps):
  97. if s.state == 'I':
  98. inactive = s
  99. break
  100. if active is not None:
  101. active.state = 'D'
  102. active.end = time.time()
  103. FermenterStep.update(**active.__dict__)
  104. del cbpi.cache["fermenter_task"][id]
  105. if inactive is not None:
  106. fermenter = self.get_fermenter(inactive.fermenter_id)
  107. current_temp = cbpi.sensor.get_value(int(fermenter.sensor))
  108. inactive.state = 'A'
  109. inactive.start = time.time()
  110. inactive.direction = "C" if current_temp >= inactive.temp else "H"
  111. FermenterStep.update(**inactive.__dict__)
  112. self.postTargetTemp(id, inactive.temp)
  113. cbpi.cache["fermenter_task"][id] = inactive
  114. cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
  115. return ('', 204)
  116. @route('/<int:id>/reset', methods=["POST"])
  117. def reset(self, id):
  118. FermenterStep.reset_all_steps(id)
  119. cbpi.cache[self.cache_key][id].steps = FermenterStep.get_by_fermenter_id(id)
  120. if id in cbpi.cache["fermenter_task"]:
  121. del cbpi.cache["fermenter_task"][id]
  122. cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
  123. return ('', 204)
  124. @route('/<int:id>/automatic', methods=['POST'])
  125. def toggle(self, id):
  126. fermenter = cbpi.cache.get(self.cache_key)[id]
  127. try:
  128. if fermenter.state is False:
  129. # Start controller
  130. if fermenter.logic is not None:
  131. cfg = fermenter.config.copy()
  132. cfg.update(
  133. dict(api=cbpi, fermenter_id=fermenter.id, heater=fermenter.heater, sensor=fermenter.sensor))
  134. instance = cbpi.fermentation.get_controller(fermenter.logic).get("class")(**cfg)
  135. instance.init()
  136. fermenter.instance = instance
  137. def run(instance):
  138. instance.run()
  139. t = cbpi._socketio.start_background_task(target=run, instance=instance)
  140. fermenter.state = not fermenter.state
  141. cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key).get(id))
  142. cbpi.emit("FERMENTER_CONTROLLER_STARTED", id=id)
  143. else:
  144. # Stop controller
  145. fermenter.instance.stop()
  146. fermenter.state = not fermenter.state
  147. cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key).get(id))
  148. cbpi.emit("FERMENTER_CONTROLLER_STOPPED", id=id)
  149. except Exception as e:
  150. cbpi.notify("Toogle Fementer Controller failed", "Pleae check the %s configuration" % fermenter.name,
  151. type="danger", timeout=None)
  152. return ('', 500)
  153. return ('', 204)
  154. def get_fermenter(self, id):
  155. return cbpi.cache["fermenter"].get(id)
  156. def target_temp_reached(self,id, step):
  157. timestamp = time.time()
  158. days = step.days * 24 * 60 * 60
  159. hours = step.hours * 60 * 60
  160. minutes = step.minutes * 60
  161. target_time = days + hours + minutes + timestamp
  162. FermenterStep.update_timer(step.id, target_time)
  163. step.timer_start = target_time
  164. cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
  165. def check_step(self):
  166. for key, value in cbpi.cache["fermenter_task"].iteritems():
  167. try:
  168. fermenter = self.get_fermenter(key)
  169. current_temp = current_temp = cbpi.get_sensor_value(int(fermenter.sensor))
  170. if value.timer_start is None:
  171. if value.direction == "H" :
  172. if current_temp >= value.temp:
  173. self.target_temp_reached(key,value)
  174. else:
  175. if current_temp <= value.temp:
  176. self.target_temp_reached(key, value)
  177. else:
  178. if time.time() >= value.timer_start:
  179. self.start_fermentation(key)
  180. else:
  181. pass
  182. except Exception as e:
  183. pass
  184. @cbpi.addon.core.backgroundjob(key="read_target_temps_fermenter", interval=5)
  185. def read_target_temps(cbpi):
  186. """
  187. background process that reads all passive sensors in interval of 1 second
  188. :return: None
  189. """
  190. for key, value in cbpi.cache.get("fermenter").iteritems():
  191. cbpi.sensor.write_log(key, value.target_temp, prefix="fermenter")
  192. instance = FermenterView()
  193. @cbpi.addon.core.backgroundjob(key="fermentation_task", interval=1)
  194. def execute_fermentation_step(cbpi):
  195. with cbpi._app.app_context():
  196. instance.check_step()
  197. def init_active_steps():
  198. pass
  199. @cbpi.addon.core.initializer(order=1)
  200. def init(cbpi):
  201. cbpi.cache["fermenter_task"] = {}
  202. FermenterView.register(cbpi._app, route_base='/api/fermenter')
  203. FermenterView.init_cache()