autostart active fermenterstep with remaining time

This commit is contained in:
avollkopf 2022-03-02 07:53:43 +01:00
parent 5bcbb7480a
commit 1d3298fc60
6 changed files with 58 additions and 15 deletions

View file

@ -162,8 +162,7 @@ class FermenterStep:
props: Props = Props() props: Props = Props()
type: str = None type: str = None
status: StepState = StepState.INITIAL status: StepState = StepState.INITIAL
#Add end data as unixtime to setp when active endtime: int = 0 # endtime if step is active and timer is running
#step_end: float = 0
instance: str = None instance: str = None
step: dict = None step: dict = None
@ -171,7 +170,7 @@ class FermenterStep:
return "name={} props={}, type={}, instance={}".format(self.name, self.props, self.type, self.instance) return "name={} props={}, type={}, instance={}".format(self.name, self.props, self.type, self.instance)
def to_dict(self): def to_dict(self):
msg = self.instance.summary if self.instance is not None else "" 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())

View file

@ -136,6 +136,7 @@ class CBPiFermentationStep(CBPiBase):
self.timer = None self.timer = None
self._done_callback = on_done self._done_callback = on_done
self.props = props self.props = props
self.endtime = int(step.get("endtime"))
self.cancel_reason: StepResult = None self.cancel_reason: StepResult = None
self.summary = "" self.summary = ""
self.task = None self.task = None
@ -187,8 +188,11 @@ class CBPiFermentationStep(CBPiBase):
async def on_props_update(self, props): async def on_props_update(self, props):
self.props = {**self.props, **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): async def save_props(self):
await self.cbpi.step.save() self.cbpi.fermenter.save()
async def push_update(self): async def push_update(self):
self.cbpi.fermenter.push_update(self.update_key) self.cbpi.fermenter.push_update(self.update_key)

View file

@ -163,6 +163,11 @@ class FermentationController:
id = item.get("id") id = item.get("id")
name = item.get("name") name = item.get("name")
props = Props(item.get("props")) props = Props(item.get("props"))
try:
endtime = int(item.get("endtime", 0))
except:
endtime=0
status = StepState(item.get("status", "I")) status = StepState(item.get("status", "I"))
if status == StepState.ACTIVE: if status == StepState.ACTIVE:
status = StepState("S") status = StepState("S")
@ -176,7 +181,7 @@ class FermentationController:
logging.warning("Failed to create step instance %s - %s" % (id, e)) logging.warning("Failed to create step instance %s - %s" % (id, e))
instance = None 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 return step
def _done(self, step_instance, result, fermenter): def _done(self, step_instance, result, fermenter):
@ -345,21 +350,22 @@ class FermentationController:
props = item.get("props") props = item.get("props")
status = StepState("I") status = StepState("I")
type = item.get("type") type = item.get("type")
#logging.info(type) endtime = 0
name = item.get("name") name = item.get("name")
props = Props(item.get("props")) props = Props(item.get("props"))
logging.info("update step") logging.info("update step")
try: try:
type_cfg = self.steptypes.get(type) type_cfg = self.steptypes.get(type)
#logging.info(type_cfg) logging.info(type_cfg)
clazz = type_cfg.get("class") clazz = type_cfg.get("class")
#logging.info(clazz) logging.info(clazz)
instance = clazz(self.cbpi, fermenter, item, props, self._done) instance = clazz(self.cbpi, fermenter, item, props, self._done)
logging.info(instance)
except Exception as e: except Exception as e:
logging.warning("Failed to create step instance %s - %s " % (item.id, e)) logging.warning("Failed to create step instance %s - %s " % (item.id, e))
instance = None 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(step)
#logging.info(fermenter.steps) #logging.info(fermenter.steps)
try: try:
@ -386,6 +392,15 @@ class FermentationController:
self.save() self.save()
self.push_update("fermenterstepupdate") 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): def _find_by_status(self, data, status):
return next((item for item in data if item.status == status), None) 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) step = self._find_by_status(item.steps, StepState.STOP)
if step is not None: if step is not None:
endtime = step.endtime
await step.instance.start() await step.instance.start()
logging.info("Restarting step {}".format(step.name)) logging.info("Restarting step {}".format(step.name))
step.status = StepState.ACTIVE step.status = StepState.ACTIVE
@ -418,6 +434,7 @@ class FermentationController:
if step is None: if step is None:
self.logger.info("No futher step to start") self.logger.info("No futher step to start")
else: else:
step.instance.endtime = 0
await step.instance.start() await step.instance.start()
logging.info("Starting step {}".format(step.name)) logging.info("Starting step {}".format(step.name))
step.status = StepState.ACTIVE step.status = StepState.ACTIVE
@ -525,6 +542,7 @@ class FermentationController:
await step.instance.stop() await step.instance.stop()
await step.instance.reset() await step.instance.reset()
step.status = StepState.INITIAL step.status = StepState.INITIAL
step.endtime = 0
except Exception as e: except Exception as e:
self.logger.error(e) self.logger.error(e)
self.save() self.save()

View file

@ -154,6 +154,8 @@ class FermenterStep(CBPiFermentationStep):
self.cbpi.notify(self.name, 'Timer started', NotificationType.INFO) self.cbpi.notify(self.name, 'Timer started', NotificationType.INFO)
self.timer.start() self.timer.start()
self.timer.is_running = True self.timer.is_running = True
self.endtime = time.time() + self.fermentationtime
await self.update_endtime()
estimated_completion_time = datetime.fromtimestamp(time.time()+ self.fermentationtime) 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) self.cbpi.notify(self.name, 'Timer started. Estimated completion: {}'.format(estimated_completion_time.strftime("%d.%m, %H:%M")), NotificationType.INFO)
else: else:
@ -184,10 +186,13 @@ class FermenterStep(CBPiFermentationStep):
async def on_start(self): async def on_start(self):
self.shutdown = False self.shutdown = False
if self.endtime == 0:
timeD=int(self.props.get("TimerD", 0)) timeD=int(self.props.get("TimerD", 0))
timeH=int(self.props.get("TimerH", 0)) timeH=int(self.props.get("TimerH", 0))
timeM=int(self.props.get("TimerM", 0)) timeM=int(self.props.get("TimerM", 0))
self.fermentationtime=(timeM+(60*timeH)+(1440*timeD)) *60 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.AutoMode = True if self.props.get("AutoMode", "No") == "Yes" else False
self.starttemp= self.get_sensor_value(self.props.get("Sensor", None)).get("value") self.starttemp= self.get_sensor_value(self.props.get("Sensor", None)).get("value")
@ -203,9 +208,16 @@ class FermenterStep(CBPiFermentationStep):
try: try:
if self.timer.is_running == True: if self.timer.is_running == True:
self.timer.start() self.timer.start()
self.endtime = time.time() + self.fermentationtime
await self.update_endtime()
except: except:
pass 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" self.summary = "Waiting for Target Temp"
await self.push_update() await self.push_update()
@ -217,7 +229,13 @@ class FermenterStep(CBPiFermentationStep):
await self.push_update() await self.push_update()
async def reset(self): 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.timer = Timer(self.fermentationtime ,on_update=self.on_timer_update, on_done=self.on_timer_done)
self.endtime = 0
self.timer.is_running == False self.timer.is_running == False
async def run(self): 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: if sensor_value >= self.fermenter.target_temp and self.timer.is_running is not True:
self.timer.start() self.timer.start()
self.timer.is_running = True self.timer.is_running = True
self.endtime = time.time() + self.fermentationtime
await self.update_endtime()
estimated_completion_time = datetime.fromtimestamp(time.time()+ self.fermentationtime) 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) 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: 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: if sensor_value <= self.fermenter.target_temp and self.timer.is_running is not True:
self.timer.start() self.timer.start()
self.timer.is_running = True self.timer.is_running = True
self.endtime = time.time() + self.fermentationtime
await self.update_endtime()
estimated_completion_time = datetime.fromtimestamp(time.time()+ self.fermentationtime) 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) self.cbpi.notify(self.name, 'Timer started. Estimated completion: {}'.format(estimated_completion_time.strftime("%d.%m, %H:%M")), NotificationType.INFO)

View file

@ -32,7 +32,7 @@ class FermenterAutostart(CBPiExtension):
self.fermenter=self.cbpi.fermenter._find_by_id(fermenter_id) self.fermenter=self.cbpi.fermenter._find_by_id(fermenter_id)
try: try:
if (self.fermenter.instance is None or self.fermenter.instance.state == False): 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)) logging.info("Successfully switched on Ferenterlogic for Fermenter {}".format(self.fermenter.id))
except Exception as e: except Exception as e:
logging.error("Failed to switch on FermenterLogic {} {}".format(self.fermenter.id, e)) logging.error("Failed to switch on FermenterLogic {} {}".format(self.fermenter.id, e))

View file

@ -352,7 +352,7 @@ class FermentationHttpEndpoints():
data = await request.json() data = await request.json()
stepid = request.match_info['stepid'] stepid = request.match_info['stepid']
fermenterid = request.match_info['fermenterid'] 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")) #step = FermenterStep(stepid, data.get("name"), None, Props(data.get("props", {})), data.get("type"))
await self.controller.update_step(fermenterid,updatedstep) await self.controller.update_step(fermenterid,updatedstep)
return web.Response(status=200) return web.Response(status=200)