2019-01-05 20:43:48 +01:00
|
|
|
import asyncio
|
2021-04-04 15:54:10 +02:00
|
|
|
import logging
|
2021-03-15 19:54:22 +01:00
|
|
|
from abc import abstractmethod
|
2022-02-21 07:16:34 +01:00
|
|
|
import cbpi
|
2021-02-16 20:37:51 +01:00
|
|
|
|
2021-02-10 07:38:55 +01:00
|
|
|
from cbpi.api.base import CBPiBase
|
2021-02-16 20:37:51 +01:00
|
|
|
|
2022-01-05 06:46:35 +01:00
|
|
|
__all__ = ["StepResult", "StepState", "StepMove", "CBPiStep", "CBPiFermentationStep"]
|
2021-02-16 20:37:51 +01:00
|
|
|
|
2021-02-10 07:38:55 +01:00
|
|
|
from enum import Enum
|
2021-01-17 22:49:18 +01:00
|
|
|
|
2021-04-04 15:54:10 +02:00
|
|
|
logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
|
|
|
|
datefmt='%Y-%m-%d:%H:%M:%S',
|
|
|
|
level=logging.INFO)
|
|
|
|
|
|
|
|
|
2021-03-15 19:54:22 +01:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
class StepResult(Enum):
|
2021-03-15 19:54:22 +01:00
|
|
|
STOP = 1
|
|
|
|
NEXT = 2
|
|
|
|
DONE = 3
|
|
|
|
ERROR = 4
|
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
|
|
|
|
class StepState(Enum):
|
2021-03-15 19:54:22 +01:00
|
|
|
INITIAL = "I"
|
|
|
|
DONE = "D"
|
|
|
|
ACTIVE = "A"
|
|
|
|
ERROR = "E"
|
|
|
|
STOP = "S"
|
|
|
|
|
2021-02-10 07:38:55 +01:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
class StepMove(Enum):
|
2021-03-15 19:54:22 +01:00
|
|
|
UP = -1
|
|
|
|
DOWN = 1
|
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
|
|
|
|
class CBPiStep(CBPiBase):
|
|
|
|
|
|
|
|
def __init__(self, cbpi, id, name, props, on_done) -> None:
|
|
|
|
self.name = name
|
2021-01-17 22:49:18 +01:00
|
|
|
self.cbpi = cbpi
|
|
|
|
self.id = id
|
2021-02-16 20:37:51 +01:00
|
|
|
self.timer = None
|
|
|
|
self._done_callback = on_done
|
|
|
|
self.props = props
|
|
|
|
self.cancel_reason: StepResult = None
|
|
|
|
self.summary = ""
|
2021-04-04 15:54:10 +02:00
|
|
|
self.task = None
|
2021-03-15 19:54:22 +01:00
|
|
|
self.running: bool = False
|
2021-04-04 15:54:10 +02:00
|
|
|
self.logger = logging.getLogger(__name__)
|
2021-02-10 07:38:55 +01:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
def _done(self, task):
|
2021-04-04 15:54:10 +02:00
|
|
|
if self._done_callback is not None:
|
|
|
|
try:
|
|
|
|
result = task.result()
|
|
|
|
self._done_callback(self, result)
|
|
|
|
except Exception as e:
|
|
|
|
self.logger.error(e)
|
2021-02-10 07:38:55 +01:00
|
|
|
|
|
|
|
async def start(self):
|
2021-04-04 15:54:10 +02:00
|
|
|
self.logger.info("Start {}".format(self.name))
|
2021-03-15 19:54:22 +01:00
|
|
|
self.running = True
|
2021-02-16 20:37:51 +01:00
|
|
|
self.task = asyncio.create_task(self._run())
|
|
|
|
self.task.add_done_callback(self._done)
|
|
|
|
|
2021-03-15 19:54:22 +01:00
|
|
|
async def next(self):
|
|
|
|
self.running = False
|
2021-02-16 20:37:51 +01:00
|
|
|
self.cancel_reason = StepResult.NEXT
|
|
|
|
self.task.cancel()
|
|
|
|
await self.task
|
2021-01-17 22:49:18 +01:00
|
|
|
|
2021-03-15 19:54:22 +01:00
|
|
|
async def stop(self):
|
2021-02-16 20:37:51 +01:00
|
|
|
try:
|
2021-03-15 19:54:22 +01:00
|
|
|
self.running = False
|
2021-04-04 15:54:10 +02:00
|
|
|
if self.task is not None and self.task.done() is False:
|
|
|
|
self.cancel_reason = StepResult.STOP
|
|
|
|
self.task.cancel()
|
|
|
|
await self.task
|
|
|
|
except Exception as e:
|
2022-02-21 07:16:34 +01:00
|
|
|
logging.error(e)
|
2021-04-04 15:54:10 +02:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
async def reset(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
async def on_props_update(self, props):
|
|
|
|
self.props = {**self.props, **props}
|
|
|
|
|
2021-03-07 23:52:20 +01:00
|
|
|
async def save_props(self):
|
|
|
|
await self.cbpi.step.save()
|
2021-03-15 19:54:22 +01:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
async def push_update(self):
|
|
|
|
self.cbpi.step.push_udpate()
|
2021-02-10 07:38:55 +01:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
async def on_start(self):
|
|
|
|
pass
|
2021-01-17 22:49:18 +01:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
async def on_stop(self):
|
|
|
|
pass
|
2021-01-17 22:49:18 +01:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
async def _run(self):
|
2021-02-10 07:38:55 +01:00
|
|
|
try:
|
2021-02-16 20:37:51 +01:00
|
|
|
await self.on_start()
|
|
|
|
await self.run()
|
|
|
|
self.cancel_reason = StepResult.DONE
|
2021-03-15 19:54:22 +01:00
|
|
|
except asyncio.CancelledError as e:
|
2021-02-16 20:37:51 +01:00
|
|
|
pass
|
|
|
|
finally:
|
|
|
|
await self.on_stop()
|
2021-03-15 19:54:22 +01:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
return self.cancel_reason
|
|
|
|
|
2021-01-17 22:49:18 +01:00
|
|
|
@abstractmethod
|
2021-02-16 20:37:51 +01:00
|
|
|
async def run(self):
|
2021-01-17 22:49:18 +01:00
|
|
|
pass
|
2019-01-05 20:43:48 +01:00
|
|
|
|
2021-02-16 20:37:51 +01:00
|
|
|
def __str__(self):
|
|
|
|
return "name={} props={}, type={}".format(self.name, self.props, self.__class__.__name__)
|
2021-04-04 15:54:10 +02:00
|
|
|
|
2022-02-21 07:16:34 +01:00
|
|
|
#class CBPiFermentationStep(CBPiStep):
|
|
|
|
|
|
|
|
# def __init__(self, cbpi, fermenter, step, props, on_done) -> None:
|
|
|
|
# self.fermenter = fermenter
|
|
|
|
# id = step.get("id")
|
|
|
|
# name=step.get("name")
|
|
|
|
# self.step=step
|
|
|
|
# super().__init__(cbpi, id, name, props, on_done)
|
|
|
|
|
|
|
|
class CBPiFermentationStep(CBPiBase):
|
2021-04-04 15:54:10 +02:00
|
|
|
|
|
|
|
def __init__(self, cbpi, fermenter, step, props, on_done) -> None:
|
|
|
|
self.fermenter = fermenter
|
2022-02-21 07:16:34 +01:00
|
|
|
self.name = step.get("name")
|
|
|
|
self.cbpi = cbpi
|
|
|
|
self.id = step.get("id")
|
|
|
|
self.timer = None
|
|
|
|
self._done_callback = on_done
|
|
|
|
self.props = props
|
2022-03-02 07:53:43 +01:00
|
|
|
self.endtime = int(step.get("endtime"))
|
2022-02-21 07:16:34 +01:00
|
|
|
self.cancel_reason: StepResult = None
|
|
|
|
self.summary = ""
|
|
|
|
self.task = None
|
|
|
|
self.running: bool = False
|
|
|
|
self.logger = logging.getLogger(__name__)
|
|
|
|
self.step = step
|
|
|
|
self.update_key="fermenterstepupdate"
|
|
|
|
|
|
|
|
def _done(self, task):
|
|
|
|
if self._done_callback is not None:
|
|
|
|
try:
|
|
|
|
result = task.result()
|
|
|
|
logging.info(result)
|
|
|
|
logging.info(self.fermenter.id)
|
|
|
|
fermenter=self.fermenter.id
|
|
|
|
self._done_callback(self, result, fermenter)
|
|
|
|
except Exception as e:
|
|
|
|
self.logger.error(e)
|
|
|
|
|
|
|
|
async def start(self):
|
|
|
|
self.logger.info("Start {}".format(self.name))
|
|
|
|
self.running = True
|
|
|
|
self.task = asyncio.create_task(self._run())
|
|
|
|
self.task.add_done_callback(self._done)
|
|
|
|
|
2022-02-21 19:39:36 +01:00
|
|
|
async def next(self, fermenter=None):
|
|
|
|
if fermenter is None:
|
|
|
|
self.running = False
|
|
|
|
self.cancel_reason = StepResult.NEXT
|
|
|
|
self.task.cancel()
|
|
|
|
await self.task
|
|
|
|
else:
|
|
|
|
await self.cbpi.fermenter.next(fermenter)
|
2022-02-21 07:16:34 +01:00
|
|
|
|
|
|
|
async def stop(self):
|
|
|
|
try:
|
|
|
|
self.running = False
|
|
|
|
if self.task is not None and self.task.done() is False:
|
|
|
|
self.cancel_reason = StepResult.STOP
|
|
|
|
logging.info(self.cancel_reason)
|
|
|
|
self.task.cancel()
|
|
|
|
await self.task
|
|
|
|
except Exception as e:
|
|
|
|
logging.error(e)
|
|
|
|
|
|
|
|
async def reset(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
async def on_props_update(self, props):
|
|
|
|
self.props = {**self.props, **props}
|
|
|
|
|
2022-03-02 07:53:43 +01:00
|
|
|
async def update_endtime(self):
|
|
|
|
await self.cbpi.fermenter.update_endtime(self.fermenter.id, self.id, self.endtime)
|
|
|
|
|
2022-02-21 07:16:34 +01:00
|
|
|
async def save_props(self):
|
2022-03-02 07:53:43 +01:00
|
|
|
self.cbpi.fermenter.save()
|
2022-02-21 07:16:34 +01:00
|
|
|
|
|
|
|
async def push_update(self):
|
|
|
|
self.cbpi.fermenter.push_update(self.update_key)
|
|
|
|
|
|
|
|
async def on_start(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
async def on_stop(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
async def _run(self):
|
|
|
|
try:
|
|
|
|
await self.on_start()
|
|
|
|
await self.run()
|
|
|
|
self.cancel_reason = StepResult.DONE
|
|
|
|
except asyncio.CancelledError as e:
|
|
|
|
pass
|
|
|
|
finally:
|
|
|
|
await self.on_stop()
|
|
|
|
|
|
|
|
return self.cancel_reason
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
async def run(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return "name={} props={}, type={}".format(self.name, self.props, self.__class__.__name__)
|