diff --git a/cbpi/api/dataclasses.py b/cbpi/api/dataclasses.py index 2cb1477..ffb6963 100644 --- a/cbpi/api/dataclasses.py +++ b/cbpi/api/dataclasses.py @@ -162,8 +162,7 @@ class FermenterStep: props: Props = Props() type: str = None status: StepState = StepState.INITIAL - #Add end data as unixtime to setp when active - #step_end: float = 0 + endtime: int = 0 # endtime if step is active and timer is running instance: str = None step: dict = None @@ -171,7 +170,7 @@ class FermenterStep: return "name={} props={}, type={}, instance={}".format(self.name, self.props, self.type, self.instance) def to_dict(self): msg = self.instance.summary if self.instance is not None else "" - return dict(id=self.id, name=self.name, state_text=msg, type=self.type, status=self.status.value, props=self.props.to_dict()) + return dict(id=self.id, name=self.name, state_text=msg, type=self.type, status=self.status.value, endtime=self.endtime, props=self.props.to_dict()) diff --git a/cbpi/api/step.py b/cbpi/api/step.py index e14e292..a9d6d19 100644 --- a/cbpi/api/step.py +++ b/cbpi/api/step.py @@ -136,6 +136,7 @@ class CBPiFermentationStep(CBPiBase): self.timer = None self._done_callback = on_done self.props = props + self.endtime = int(step.get("endtime")) self.cancel_reason: StepResult = None self.summary = "" self.task = None @@ -187,8 +188,11 @@ class CBPiFermentationStep(CBPiBase): async def on_props_update(self, props): self.props = {**self.props, **props} + async def update_endtime(self): + await self.cbpi.fermenter.update_endtime(self.fermenter.id, self.id, self.endtime) + async def save_props(self): - await self.cbpi.step.save() + self.cbpi.fermenter.save() async def push_update(self): self.cbpi.fermenter.push_update(self.update_key) diff --git a/cbpi/controller/fermentation_controller.py b/cbpi/controller/fermentation_controller.py index c0134fd..5a8d294 100644 --- a/cbpi/controller/fermentation_controller.py +++ b/cbpi/controller/fermentation_controller.py @@ -163,6 +163,11 @@ class FermentationController: id = item.get("id") name = item.get("name") props = Props(item.get("props")) + try: + endtime = int(item.get("endtime", 0)) + except: + endtime=0 + status = StepState(item.get("status", "I")) if status == StepState.ACTIVE: status = StepState("S") @@ -176,7 +181,7 @@ class FermentationController: logging.warning("Failed to create step instance %s - %s" % (id, e)) instance = None - step = FermenterStep(id=id, name=name, fermenter=fermenter, props=props, type=type, status=status, instance=instance) + step = FermenterStep(id=id, name=name, fermenter=fermenter, props=props, type=type, status=status, endtime=endtime, instance=instance) return step def _done(self, step_instance, result, fermenter): @@ -345,21 +350,22 @@ class FermentationController: props = item.get("props") status = StepState("I") type = item.get("type") - #logging.info(type) + endtime = 0 name = item.get("name") props = Props(item.get("props")) logging.info("update step") try: type_cfg = self.steptypes.get(type) - #logging.info(type_cfg) + logging.info(type_cfg) clazz = type_cfg.get("class") - #logging.info(clazz) + logging.info(clazz) instance = clazz(self.cbpi, fermenter, item, props, self._done) + logging.info(instance) except Exception as e: logging.warning("Failed to create step instance %s - %s " % (item.id, e)) instance = None - step = FermenterStep(id=stepid, name=name, fermenter=fermenter, props=props, type=type, status=status, instance=instance) + step = FermenterStep(id=stepid, name=name, fermenter=fermenter, props=props, type=type, status=status, endtime=endtime, instance=instance) #logging.info(step) #logging.info(fermenter.steps) try: @@ -386,6 +392,15 @@ class FermentationController: self.save() self.push_update("fermenterstepupdate") + async def update_endtime(self, id, stepid, endtime): + try: + item = self._find_by_id(id) + step = self._find_step_by_id(item.steps, stepid) + step.endtime = int(endtime) + self.save() + self.push_update("fermenterstepupdate") + except Exception as e: + self.logger.error(e) def _find_by_status(self, data, status): return next((item for item in data if item.status == status), None) @@ -405,6 +420,7 @@ class FermentationController: step = self._find_by_status(item.steps, StepState.STOP) if step is not None: + endtime = step.endtime await step.instance.start() logging.info("Restarting step {}".format(step.name)) step.status = StepState.ACTIVE @@ -418,6 +434,7 @@ class FermentationController: if step is None: self.logger.info("No futher step to start") else: + step.instance.endtime = 0 await step.instance.start() logging.info("Starting step {}".format(step.name)) step.status = StepState.ACTIVE @@ -525,6 +542,7 @@ class FermentationController: await step.instance.stop() await step.instance.reset() step.status = StepState.INITIAL + step.endtime = 0 except Exception as e: self.logger.error(e) self.save() diff --git a/cbpi/extension/FermentationStep/__init__.py b/cbpi/extension/FermentationStep/__init__.py index 7660176..130604c 100644 --- a/cbpi/extension/FermentationStep/__init__.py +++ b/cbpi/extension/FermentationStep/__init__.py @@ -154,6 +154,8 @@ class FermenterStep(CBPiFermentationStep): self.cbpi.notify(self.name, 'Timer started', NotificationType.INFO) self.timer.start() self.timer.is_running = True + self.endtime = time.time() + self.fermentationtime + await self.update_endtime() estimated_completion_time = datetime.fromtimestamp(time.time()+ self.fermentationtime) self.cbpi.notify(self.name, 'Timer started. Estimated completion: {}'.format(estimated_completion_time.strftime("%d.%m, %H:%M")), NotificationType.INFO) else: @@ -184,10 +186,13 @@ class FermenterStep(CBPiFermentationStep): async def on_start(self): self.shutdown = False - timeD=int(self.props.get("TimerD", 0)) - timeH=int(self.props.get("TimerH", 0)) - timeM=int(self.props.get("TimerM", 0)) - self.fermentationtime=(timeM+(60*timeH)+(1440*timeD)) *60 + if self.endtime == 0: + timeD=int(self.props.get("TimerD", 0)) + timeH=int(self.props.get("TimerH", 0)) + timeM=int(self.props.get("TimerM", 0)) + self.fermentationtime=(timeM+(60*timeH)+(1440*timeD)) *60 + else: + self.fermentationtime = self.endtime - time.time() self.AutoMode = True if self.props.get("AutoMode", "No") == "Yes" else False self.starttemp= self.get_sensor_value(self.props.get("Sensor", None)).get("value") @@ -203,9 +208,16 @@ class FermenterStep(CBPiFermentationStep): try: if self.timer.is_running == True: self.timer.start() + self.endtime = time.time() + self.fermentationtime + await self.update_endtime() except: pass + if self.endtime != 0 and self.timer is not None and self.timer.is_running == False: + self.timer.start() + self.timer.is_running = True + + self.summary = "Waiting for Target Temp" await self.push_update() @@ -217,7 +229,13 @@ class FermenterStep(CBPiFermentationStep): await self.push_update() async def reset(self): + #await self.timer.stop() + timeD=int(self.props.get("TimerD", 0)) + timeH=int(self.props.get("TimerH", 0)) + timeM=int(self.props.get("TimerM", 0)) + self.fermentationtime=(timeM+(60*timeH)+(1440*timeD)) *60 self.timer = Timer(self.fermentationtime ,on_update=self.on_timer_update, on_done=self.on_timer_done) + self.endtime = 0 self.timer.is_running == False async def run(self): @@ -229,6 +247,8 @@ class FermenterStep(CBPiFermentationStep): if sensor_value >= self.fermenter.target_temp and self.timer.is_running is not True: self.timer.start() self.timer.is_running = True + self.endtime = time.time() + self.fermentationtime + await self.update_endtime() estimated_completion_time = datetime.fromtimestamp(time.time()+ self.fermentationtime) self.cbpi.notify(self.name, 'Timer started. Estimated completion: {}'.format(estimated_completion_time.strftime("%d.%m, %H:%M")), NotificationType.INFO) elif self.fermenter.target_temp <= self.starttemp: @@ -239,6 +259,8 @@ class FermenterStep(CBPiFermentationStep): if sensor_value <= self.fermenter.target_temp and self.timer.is_running is not True: self.timer.start() self.timer.is_running = True + self.endtime = time.time() + self.fermentationtime + await self.update_endtime() estimated_completion_time = datetime.fromtimestamp(time.time()+ self.fermentationtime) self.cbpi.notify(self.name, 'Timer started. Estimated completion: {}'.format(estimated_completion_time.strftime("%d.%m, %H:%M")), NotificationType.INFO) diff --git a/cbpi/extension/FermenterHysteresis/__init__.py b/cbpi/extension/FermenterHysteresis/__init__.py index 4ed1561..5be707c 100644 --- a/cbpi/extension/FermenterHysteresis/__init__.py +++ b/cbpi/extension/FermenterHysteresis/__init__.py @@ -32,7 +32,7 @@ class FermenterAutostart(CBPiExtension): self.fermenter=self.cbpi.fermenter._find_by_id(fermenter_id) try: if (self.fermenter.instance is None or self.fermenter.instance.state == False): - await self.cbpi.fermenter.toggle(self.fermenter.id) + await self.cbpi.fermenter.start(self.fermenter.id) logging.info("Successfully switched on Ferenterlogic for Fermenter {}".format(self.fermenter.id)) except Exception as e: logging.error("Failed to switch on FermenterLogic {} {}".format(self.fermenter.id, e)) diff --git a/cbpi/http_endpoints/http_fermentation.py b/cbpi/http_endpoints/http_fermentation.py index 1eec644..945743c 100644 --- a/cbpi/http_endpoints/http_fermentation.py +++ b/cbpi/http_endpoints/http_fermentation.py @@ -352,7 +352,7 @@ class FermentationHttpEndpoints(): data = await request.json() stepid = request.match_info['stepid'] fermenterid = request.match_info['fermenterid'] - updatedstep = {"id": stepid, "name": data.get("name"), "props": data.get("props", {}), "type": data.get("type")} + updatedstep = {"id": stepid, "name": data.get("name"), "endtime": 0, "props": data.get("props", {}), "type": data.get("type")} #step = FermenterStep(stepid, data.get("name"), None, Props(data.get("props", {})), data.get("type")) await self.controller.update_step(fermenterid,updatedstep) return web.Response(status=200)