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.

273 lines
9.1KB

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