craftbeerpi4-pione/cbpi/controller/step_controller.py

195 lines
5.9 KiB
Python
Raw Normal View History

2019-01-04 09:29:09 +01:00
import logging
2018-12-16 21:42:47 +01:00
import time
2019-01-02 00:48:36 +01:00
2019-01-05 20:43:48 +01:00
from cbpi.api import *
from cbpi.controller.crud_controller import CRUDController
from cbpi.database.model import StepModel
2018-12-03 22:16:03 +01:00
2018-12-08 14:21:00 +01:00
2019-01-02 21:20:44 +01:00
class StepController(CRUDController):
2018-12-09 22:20:33 +01:00
2019-07-27 21:08:19 +02:00
2018-11-29 21:59:08 +01:00
2018-12-03 22:16:03 +01:00
def __init__(self, cbpi):
2019-07-27 21:08:19 +02:00
self.model = StepModel
self.caching = True
2019-01-04 09:29:09 +01:00
self.is_stopping = False
2018-12-03 22:16:03 +01:00
self.cbpi = cbpi
2018-12-05 07:31:12 +01:00
self.current_task = None
2019-01-04 09:29:09 +01:00
self.is_next = False
2018-12-03 22:16:03 +01:00
self.types = {}
self.current_step = None
2019-01-02 00:48:36 +01:00
self.current_job = None
2019-01-02 21:20:44 +01:00
self.cbpi.register(self)
2019-01-04 09:29:09 +01:00
self.logger = logging.getLogger(__name__)
self.starttime = None
2018-12-15 00:01:37 +01:00
2019-07-27 21:08:19 +02:00
def is_running(self):
if self.current_step is not None:
return True
else:
return False
2018-12-07 23:57:32 +01:00
2019-07-27 21:08:19 +02:00
def _get_manged_fields_as_array(self, type_cfg):
2019-07-27 21:08:19 +02:00
result = []
2018-12-07 23:57:32 +01:00
2019-07-27 21:08:19 +02:00
for f in type_cfg.get("properties"):
2018-12-03 22:16:03 +01:00
2019-07-27 21:08:19 +02:00
result.append(f.get("name"))
2018-12-15 00:01:37 +01:00
2019-07-27 21:08:19 +02:00
return result
2018-12-15 00:01:37 +01:00
2019-07-27 21:08:19 +02:00
async def init(self):
2018-12-09 22:20:33 +01:00
2019-07-27 21:08:19 +02:00
# load all steps into cache
self.cache = await self.model.get_all()
2018-12-15 00:01:37 +01:00
2019-01-04 09:29:09 +01:00
2019-07-27 21:08:19 +02:00
for key, value in self.cache.items():
2019-01-04 09:29:09 +01:00
2019-07-27 21:08:19 +02:00
# get step type as string
step_type = self.types.get(value.type)
2018-12-05 07:31:12 +01:00
2019-07-27 21:08:19 +02:00
# if step has state
if value.stepstate is not None:
cfg = value.stepstate.copy()
else:
cfg = {}
2018-12-05 07:31:12 +01:00
2019-07-27 21:08:19 +02:00
# set managed fields
cfg.update(dict(cbpi=self.cbpi, id=value.id, managed_fields=self._get_manged_fields_as_array(step_type)))
2018-12-29 00:27:19 +01:00
2019-07-27 21:08:19 +02:00
if value.config is not None:
# set config values
cfg.update(**value.config)
# create step instance
value.instance = step_type["class"](**cfg)
2018-12-05 07:31:12 +01:00
2019-07-27 21:08:19 +02:00
async def get_all(self, force_db_update: bool = True):
return self.cache
2018-12-03 22:16:03 +01:00
2019-07-27 21:08:19 +02:00
def find_next_step(self):
# filter
inactive_steps = {k: v for k, v in self.cache.items() if v.state == 'I'}
if len(inactive_steps) == 0:
return None
return min(inactive_steps, key=lambda x: inactive_steps[x].order)
2019-01-02 00:48:36 +01:00
@on_event("step/start")
2019-01-04 09:29:09 +01:00
async def start(self, **kwargs):
2018-12-03 22:16:03 +01:00
2019-01-04 09:29:09 +01:00
if self.is_running() is False:
2019-07-27 21:08:19 +02:00
next_step_id = self.find_next_step()
if next_step_id:
next_step = self.cache[next_step_id]
2019-01-04 09:29:09 +01:00
next_step.state = 'A'
next_step.stepstate = next_step.config
next_step.start = int(time.time())
await self.model.update(**next_step.__dict__)
2019-07-27 21:08:19 +02:00
self.current_step = next_step
# start the step job
self.current_job = await self.cbpi.job.start_job(self.current_step.instance.run(), next_step.name, "step")
2019-07-31 07:58:54 +02:00
await self.cbpi.bus.fire("step/%s/started" % self.current_step.id, step=next_step)
2018-12-16 21:42:47 +01:00
else:
2019-01-04 09:29:09 +01:00
await self.cbpi.bus.fire("step/brewing/finished")
else:
self.logger.error("Process Already Running")
2019-01-28 22:21:31 +01:00
2019-07-27 21:08:19 +02:00
async def next(self, **kwargs):
2019-01-04 09:29:09 +01:00
if self.current_step is not None:
2019-07-27 21:08:19 +02:00
self.is_next = True
self.current_step.instance.stop()
2019-01-04 09:29:09 +01:00
2019-07-27 21:08:19 +02:00
@on_event("job/step/done")
async def step_done(self, **kwargs):
if self.cbpi.shutdown:
return
if self.is_stopping:
self.is_stopping = False
return
2019-01-04 09:29:09 +01:00
if self.current_step is not None:
2019-07-27 21:08:19 +02:00
self.current_step.state = "D"
await self.model.update_state(self.current_step.id, "D", int(time.time()))
2019-07-31 07:58:54 +02:00
await self.cbpi.bus.fire("step/%s/done" % self.current_step.id, step=self.current_step)
2019-01-04 09:29:09 +01:00
self.current_step = None
2019-07-27 21:08:19 +02:00
# start the next step
await self.start()
@on_event("step/stop")
async def stop_all(self, **kwargs):
# RESET DB
2019-01-04 09:29:09 +01:00
await self.model.reset_all_steps()
2019-07-27 21:08:19 +02:00
# RELOAD all Steps from DB into cache and initialize Instances
await self.init()
await self.cbpi.bus.fire("step/brewing/stopped")
2019-01-04 09:29:09 +01:00
2019-01-28 22:21:31 +01:00
@on_event("step/clear")
async def clear_all(self, **kwargs):
await self.model.delete_all()
self.cbpi.notify(key="Steps Cleared", message="Steps cleared successfully", type="success")
2019-01-21 22:33:29 +01:00
async def _pre_add_callback(self, data):
2019-07-27 21:08:19 +02:00
2019-01-21 22:33:29 +01:00
order = await self.model.get_max_order()
data["order"] = 1 if order is None else order + 1
data["state"] = "I"
2019-07-27 21:08:19 +02:00
data["stepstate"] = {}
2019-01-21 22:33:29 +01:00
return await super()._pre_add_callback(data)
2019-07-27 21:08:19 +02:00
async def init_step(self, value: StepModel):
step_type = self.types.get(value.type)
2019-01-21 22:33:29 +01:00
2019-07-27 21:08:19 +02:00
# if step has state
if value.stepstate is not None:
cfg = value.stepstate.copy()
else:
cfg = {}
2019-01-21 22:33:29 +01:00
2019-07-27 21:08:19 +02:00
# set managed fields
cfg.update(dict(cbpi=self.cbpi, id=value.id, managed_fields=self._get_manged_fields_as_array(step_type)))
# set config values
cfg.update(**value.config)
# create step instance
value.instance = step_type["class"](**cfg)
return value
2019-01-21 22:33:29 +01:00
2019-07-27 21:08:19 +02:00
async def _post_add_callback(self, m: StepModel) -> None:
self.cache[m.id] = await self.init_step(m)
2019-01-21 22:33:29 +01:00
2019-07-27 21:08:19 +02:00
async def _post_update_callback(self, m: StepModel) -> None:
'''
:param m: step model
:return: None
'''
self.cache[m.id] = await self.init_step(m)
@on_event("step/sort")
async def sort(self, topic: 'str', data: 'dict', **kwargs):
# update order in cache
for id, order in data.items():
self.cache[int(id)].order = order
# update oder in database
await self.model.sort(data)
async def get_state(self):
return dict(items=await self.get_all(),types=self.types,is_running=self.is_running(),current_step=self.current_step)
2019-07-31 07:58:54 +02:00
@on_event(topic="step/action")
async def call_action(self, name, parameter, **kwargs) -> None:
print(name, parameter)
if self.current_step is not None:
self.current_step.instance.__getattribute__(name)(**parameter)