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.

247 lines
6.9KB

  1. import time
  2. from flask import json, request
  3. from flask_classy import route
  4. from modules.core.db import DBModel
  5. from modules.core.baseview import RestApi
  6. from modules import cbpi
  7. from modules.database.dbmodel import Step
  8. class StepView(RestApi):
  9. model = Step
  10. def _pre_post_callback(self, data):
  11. order = self.model.get_max_order()
  12. data["order"] = 1 if order is None else order + 1
  13. data["state"] = "I"
  14. @route('/sort', methods=["POST"])
  15. def sort_steps(self):
  16. """
  17. Sort all steps
  18. ---
  19. tags:
  20. - steps
  21. responses:
  22. 204:
  23. description: Steps sorted. Update delivered via web socket
  24. """
  25. Step.sort(request.json)
  26. cbpi.ws_emit("UPDATE_ALL_STEPS", self.model.get_all())
  27. return ('', 204)
  28. @route('/', methods=["DELETE"])
  29. def deleteAll(self):
  30. """
  31. Delete all Steps
  32. ---
  33. tags:
  34. - steps
  35. responses:
  36. 204:
  37. description: All steps deleted
  38. """
  39. self.model.delete_all()
  40. self.api.emit("ALL_BREWING_STEPS_DELETED")
  41. self.api.set_config_parameter("brew_name", "")
  42. cbpi.ws_emit("UPDATE_ALL_STEPS", self.model.get_all())
  43. return ('', 204)
  44. @route('/action/<method>', methods=["POST"])
  45. def action(self, method):
  46. """
  47. Call Step Action
  48. ---
  49. tags:
  50. - steps
  51. responses:
  52. 204:
  53. description: Step action called
  54. """
  55. self.api.emit("BREWING_STEP_ACTION_INVOKED", method=method)
  56. cbpi.cache["active_step"].__getattribute__(method)()
  57. return ('', 204)
  58. @route('/reset', methods=["POST"])
  59. def reset(self):
  60. """
  61. Reset All Steps
  62. ---
  63. tags:
  64. - steps
  65. responses:
  66. 200:
  67. description: Steps reseted
  68. """
  69. self.model.reset_all_steps()
  70. self.stop_step()
  71. self.api.emit("ALL_BREWING_STEPS_RESET")
  72. cbpi.ws_emit("UPDATE_ALL_STEPS", self.model.get_all())
  73. return ('', 204)
  74. def stop_step(self):
  75. '''
  76. stop active step
  77. :return:
  78. '''
  79. step = cbpi.cache.get("active_step")
  80. cbpi.cache["active_step"] = None
  81. self.api.emit("BREWING_STEPS_STOP")
  82. if step is not None:
  83. step.finish()
  84. @route('/reset/current', methods=['POST'])
  85. def resetCurrentStep(self):
  86. """
  87. Reset current Steps
  88. ---
  89. tags:
  90. - steps
  91. responses:
  92. 200:
  93. description: Current Steps reseted
  94. """
  95. step = cbpi.cache.get("active_step")
  96. if step is not None:
  97. step.reset()
  98. if step.is_dirty():
  99. state = {}
  100. for field in step.managed_fields:
  101. state[field] = step.__getattribute__(field)
  102. Step.update_step_state(step.id, state)
  103. step.reset_dirty()
  104. self.api.emit("BREWING_STEPS_RESET_CURRENT")
  105. cbpi.ws_emit("UPDATE_ALL_STEPS", self.model.get_all())
  106. return ('', 204)
  107. def init_step(self, step):
  108. cbpi.brewing.log_action("Start Step %s" % step.name)
  109. type_cfg = cbpi.cache.get("step_types").get(step.type)
  110. if type_cfg is None:
  111. # if type not found
  112. return
  113. # copy config to stepstate
  114. # init step
  115. cfg = step.config.copy()
  116. cfg.update(dict(name=step.name, api=cbpi, id=step.id, timer_end=None, managed_fields=get_manged_fields_as_array(type_cfg)))
  117. instance = type_cfg.get("class")(**cfg)
  118. instance.init()
  119. # set step instance to ache
  120. cbpi.cache["active_step"] = instance
  121. @route('/next', methods=['POST'])
  122. @route('/start', methods=['POST'])
  123. def start(self):
  124. """
  125. Next Step
  126. ---
  127. tags:
  128. - steps
  129. responses:
  130. 200:
  131. description: Next Step
  132. """
  133. active = Step.get_by_state("A")
  134. inactive = Step.get_by_state('I')
  135. if (active is not None):
  136. active.state = 'D'
  137. active.end = int(time.time())
  138. self.stop_step()
  139. Step.update(**active.__dict__)
  140. self.api.emit("BREWING_STEP_DONE")
  141. if (inactive is not None):
  142. self.init_step(inactive)
  143. inactive.state = 'A'
  144. inactive.stepstate = inactive.config
  145. inactive.start = int(time.time())
  146. Step.update(**inactive.__dict__)
  147. self.api.emit("BREWING_STEP_STARTED")
  148. else:
  149. cbpi.brewing.log_action("Brewing Finished")
  150. self.api.emit("BREWING_FINISHED")
  151. cbpi.notify("Brewing Finished", "You are done!", timeout=None)
  152. cbpi.ws_emit("UPDATE_ALL_STEPS", Step.get_all())
  153. return ('', 204)
  154. def get_manged_fields_as_array(type_cfg):
  155. result = []
  156. for f in type_cfg.get("properties"):
  157. result.append(f.get("name"))
  158. return result
  159. def init_after_startup():
  160. '''
  161. Restart after startup. Check is a step is in state A and reinitialize
  162. :return: None
  163. '''
  164. step = Step.get_by_state('A')
  165. # We have an active step
  166. if step is not None:
  167. # get the type
  168. type_cfg = cbpi.cache.get("step_types").get(step.type)
  169. if type_cfg is None:
  170. # step type not found. cant restart step
  171. return
  172. cfg = step.stepstate.copy()
  173. cfg.update(dict(api=cbpi, id=step.id, managed_fields=get_manged_fields_as_array(type_cfg)))
  174. instance = type_cfg.get("class")(**cfg)
  175. instance.init()
  176. cbpi.cache["active_step"] = instance
  177. @cbpi.addon.core.initializer(order=2000)
  178. def init(cbpi):
  179. StepView.register(cbpi.web, route_base='/api/step')
  180. def get_all():
  181. with cbpi.web.app_context():
  182. return Step.get_all()
  183. with cbpi.web.app_context():
  184. init_after_startup()
  185. cbpi.add_cache_callback("steps", get_all)
  186. @cbpi.addon.core.backgroundtask(key="step_task", interval=0.1)
  187. def execute_step(api):
  188. '''
  189. Background job which executes the step
  190. :return:
  191. '''
  192. with cbpi.web.app_context():
  193. step = cbpi.cache.get("active_step")
  194. if step is not None:
  195. step.execute()
  196. if step.is_dirty():
  197. state = {}
  198. for field in step.managed_fields:
  199. state[field] = step.__getattribute__(field)
  200. Step.update_step_state(step.id, state)
  201. step.reset_dirty()
  202. cbpi.ws_emit("UPDATE_ALL_STEPS", Step.get_all())
  203. if step.n is True:
  204. StepView().start()
  205. cbpi.ws_emit("UPDATE_ALL_STEPS", Step.get_all())