Merge form dev branch

This commit is contained in:
Manuel Fritsch 2022-03-13 12:52:40 +01:00
commit 036e70e4bf
18 changed files with 220 additions and 239 deletions

View file

@ -1 +1 @@
__version__ = "4.0.2.0.a8"
__version__ = "4.0.2.0.a19"

View file

@ -131,7 +131,7 @@ class Fermenter:
brewname: str = None
description : str = None
props: Props = Props()
target_temp: int = 0
target_temp: float = 0
type: str = None
steps: List[Step]= field(default_factory=list)
instance: str = None
@ -162,7 +162,7 @@ class FermenterStep:
props: Props = Props()
type: str = None
status: StepState = StepState.INITIAL
endtime: int = 0 # endtime if step is active and timer is running
endtime: int = 0 # endtime if step is active and timer is running
instance: str = None
step: dict = None
@ -170,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, endtime = self.endtime, 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

@ -117,15 +117,6 @@ class CBPiStep(CBPiBase):
def __str__(self):
return "name={} props={}, type={}".format(self.name, self.props, self.__class__.__name__)
#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):
def __init__(self, cbpi, fermenter, step, props, on_done) -> None:
@ -190,9 +181,9 @@ class CBPiFermentationStep(CBPiBase):
async def update_endtime(self):
await self.cbpi.fermenter.update_endtime(self.fermenter.id, self.id, self.endtime)
async def save_props(self):
self.cbpi.fermenter.save()
self.cbpi.fermenter.save()
async def push_update(self):
self.cbpi.fermenter.push_update(self.update_key)

View file

@ -22,7 +22,7 @@ class BasicController:
self.logger = logging.getLogger(__name__)
self.data = []
self.autostart = True
self._loop = asyncio.get_event_loop()
#self._loop = asyncio.get_event_loop()
self.path = os.path.join(".", 'config', file)
self.cbpi.app.on_cleanup.append(self.shutdown)
@ -100,7 +100,8 @@ class BasicController:
await item.instance.start()
item.instance.running = True
item.instance.task = self._loop.create_task(item.instance._run())
item.instance.task = asyncio.get_event_loop().create_task(item.instance._run())
#item.instance.task = self._loop.create_task(item.instance._run())
logging.info("{} started {}".format(self.name, id))

View file

@ -15,79 +15,7 @@ from cbpi.controller.basic_controller2 import BasicController
from tabulate import tabulate
import sys, os
from ..api.step import CBPiStep, StepMove, StepResult, StepState, CBPiFermentationStep
class FermentStep:
def __init__(self, cbpi, step, on_done) -> None:
self.cbpi = cbpi
self.logger = logging.getLogger(__name__)
self.step = step
self.props = step.props
self._done_callback = on_done
self.task = None
self.summary = ""
def _done(self, task):
if self._done_callback is not None:
try:
result = task.result()
self._done_callback(self, result)
except Exception as e:
self.logger.error(e)
@abstractmethod
async def run(self):
while self.running:
logging.info(self.step)
await asyncio.sleep(1)
pass
async def _run(self):
try:
await self.step.instance.on_start()
await self.step.instance.run()
#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
async def start(self):
self.logger.info("Start {}".format(self.step.name))
self.running = True
self.task = asyncio.create_task(self._run())
self.task.add_done_callback(self._done)
async def next(self):
self.running = False
self.cancel_reason = StepResult.NEXT
self.task.cancel()
await self.task
async def stop(self):
try:
self.running = False
if self.task is not None and self.task.done() is False:
self.logger.info("Stopping Task")
self.cancel_reason = StepResult.STOP
self.task.cancel()
await self.task
except Exception as e:
self.logger.error(e)
async def on_start(self):
#self.props.hello = "WOOHOo"
pass
async def on_stop(self):
pass
class FermentationController:
def __init__(self, cbpi):
@ -95,7 +23,6 @@ class FermentationController:
self.cbpi = cbpi
self.logger = logging.getLogger(__name__)
self.path = os.path.join(".", 'config', "fermenter_data.json")
self.data = []
self.types = {}
self.steptypes = {}
@ -127,6 +54,10 @@ class FermentationController:
for step in fermenter.steps:
try:
self.logger.info("Stop {}".format(step.name))
try:
step.instance.shutdown = True
except:
pass
await step.instance.stop()
except Exception as e:
self.logger.error(e)
@ -136,15 +67,16 @@ class FermentationController:
for step in fermenter.steps:
try:
self.logger.info("Stop {}".format(step.name))
try:
step.instance.shutdown = True
except:
pass
await step.instance.stop()
except Exception as e:
self.logger.error(e)
async def load(self):
# if os.path.exists(self.path) is False:
# with open(self.path, "w") as file:
# json.dump(dict(basic={}, steps=[]), file, indent=4, sort_keys=True)
with open(self.path) as json_file:
data = json.load(json_file)
@ -155,12 +87,14 @@ 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"))
endtime = int(item.get("endtime", 0))
if status == StepState.ACTIVE:
status = StepState("S")
if status != StepState.STOP:
endtime = 0
type = item.get("type")
try:
@ -221,7 +155,6 @@ class FermentationController:
def get_state(self):
if self.data == []:
#logging.info(self.data)
pass
return {"data": list(map(lambda x: x.to_dict(), self.data)), "types":self.get_types(), "steptypes":self.get_steptypes()}
@ -238,7 +171,6 @@ class FermentationController:
def get_fermenter_steps(self):
if self.data == []:
#logging.info(self.data)
pass
fermentersteps=[]
steplist=list(map(lambda x: x.to_dict(), self.data))
@ -307,16 +239,16 @@ class FermentationController:
with open(self.path, "w") as file:
json.dump(data, file, indent=4, sort_keys=True)
async def create_step(self, id, item):
def create_step(self, id, item):
try:
stepid = shortuuid.uuid()
props = item.get("props")
item['id'] = stepid
status = StepState("I")
type = item.get("type")
name = item.get("name")
endtime = item.get("endtime", 0)
props = Props(item.get("props"))
fermenter = self._find_by_id(id)
try:
type_cfg = self.steptypes.get(type)
clazz = type_cfg.get("class")
@ -324,13 +256,8 @@ class FermentationController:
except Exception as e:
logging.warning("Failed to create step instance %s - %s" % (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)
fermenter.steps.append(step)
self.save()
self.push_update("fermenterstepupdate")
return step
except Exception as e:
self.logger.error(e)
@ -341,30 +268,29 @@ 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)
#logging.info(step)
#logging.info(fermenter.steps)
step = FermenterStep(id=stepid, name=name, fermenter=fermenter, props=props, type=type, status=status, endtime=endtime, instance=instance)
try:
fermenter.steps = list(map(lambda old: step if old.id == step.id else old, fermenter.steps))
except Exception as e:
logging.info(e)
#logging.info(fermenter.steps)
self.save()
#logging.info("SAVEUPDATE")
self.push_update("fermenterstepupdate")
@ -382,6 +308,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)
@ -419,6 +354,7 @@ class FermentationController:
logging.info("Need to change timer")
step.status = StepState.ACTIVE
self.save()
self.push_update()
self.push_update("fermenterstepupdate")
return
@ -432,6 +368,7 @@ class FermentationController:
logging.info("Starting step {}".format(step.name))
step.status = StepState.ACTIVE
self.save()
self.push_update()
self.push_update("fermenterstepupdate")
except Exception as e:
@ -517,7 +454,7 @@ class FermentationController:
await self.start(id)
else:
logging.info("No Step is running")
self.push_update()
self.push_update("fermenterstepupdate")
except Exception as e:
@ -531,12 +468,14 @@ class FermentationController:
for step in item.steps:
self.logger.info("Stopping Step {} {}".format(step.name, step.id))
try:
await step.instance.stop()
await step.instance.reset()
await step.instance.stop()
step.status = StepState.INITIAL
step.endtime = 0
except Exception as e:
self.logger.error(e)
self.save()
self.push_update()
self.push_update("fermenterstepupdate")
except Exception as e:
@ -555,6 +494,7 @@ class FermentationController:
fermenter.steps[index], fermenter.steps[index+direction] = fermenter.steps[index+direction], fermenter.steps[index]
self.save()
self.push_update()
self.push_update("fermenterstepupdate")
except Exception as e:
@ -564,15 +504,19 @@ class FermentationController:
if key == self.update_key:
self.cbpi.ws.send(dict(topic=key, data=list(map(lambda item: item.to_dict(), self.data))))
#self.cbpi.push_update("cbpi/{}".format(self.update_key), list(map(lambda item: item.to_dict(), self.data)))
for item in self.data:
self.cbpi.push_update("cbpi/{}/{}".format(self.update_key,item.id), item.to_dict())
pass
else:
#logging.info("FERMENTERSTEPUPDATE {}".format(key))
fermentersteps=self.get_fermenter_steps()
self.cbpi.ws.send(dict(topic=key, data=fermentersteps))
# send mqtt update for active femrentersteps
for fermenter in fermentersteps:
for step in fermenter['steps']:
if step['status'] == 'A':
self.cbpi.push_update("cbpi/{}/{}/{}".format(key,fermenter['id'],step['id']), step)
async def call_action(self, id, action, parameter) -> None:
logging.info("FermenterStep Controller - call Action {} {}".format(id, action))
@ -582,8 +526,7 @@ class FermentationController:
await item.instance.__getattribute__(action)(**parameter)
except Exception as e:
logging.error("FermenterStep Controller - Failed to call action on {} {} {}".format(id, action, e))
# todo: Sensors may need to be removed when saving the recipe -> need to be replaced when assinging later to Fermenter with 'fermenter.sensor'
async def savetobook(self, fermenterid):
name = shortuuid.uuid()
path = os.path.join(".", 'config', "fermenterrecipes", "{}.yaml".format(name))
@ -591,7 +534,7 @@ class FermentationController:
try:
brewname = fermenter.brewname
description = fermenter.description
# todo add escription at later point of time, once description has been added to fermenter dataclass
except:
brewname = ""
description = ""
@ -605,20 +548,38 @@ class FermentationController:
with open(path, "w") as file:
yaml.dump(data, file)
async def load_recipe(self, data, fermenterid):
async def load_recipe(self, data, fermenterid, name):
try:
await self.shutdown(None, fermenterid)
except:
pass
fermenter = self._find_by_id(fermenterid)
def add_runtime_data(item):
item["status"] = "I"
item["endtime"] = 0
item["id"] = shortuuid.uuid()
item["props"]["Sensor"] = fermenter.sensor
list(map(lambda item: add_runtime_data(item), data.get("steps")))
fermenter.description = data['basic']['desc']
fermenter.brewname = data['basic']['name']
fermenter.steps=[]
if name is not None:
fermenter.brewname = name
else:
fermenter.brewname = data['basic']['name']
await self.update(fermenter)
fermenter.steps=[]
for item in data.get("steps"):
await self.create_step(fermenterid, item)
fermenter.steps.append(self.create_step(fermenterid, item))
self.save()
self.push_update("fermenterstepupdate")
async def add_step(self, fermenterid, newstep):
fermenter = self._find_by_id(fermenterid)
step = self.create_step(fermenterid, newstep)
fermenter.steps.append(step)
self.save()
self.push_update("fermenterstepupdate")
return step

View file

@ -69,13 +69,13 @@ class FermenterRecipeController:
os.remove(path)
async def brew(self, name, fermenterid):
async def brew(self, recipeid, fermenterid, name):
recipe_path = os.path.join(".", 'config', "fermenterrecipes", "%s.yaml" % name)
recipe_path = os.path.join(".", 'config', "fermenterrecipes", "%s.yaml" % recipeid)
logging.info(recipe_path)
with open(recipe_path) as file:
data = yaml.load(file, Loader=yaml.FullLoader)
await self.cbpi.fermenter.load_recipe(data, fermenterid)
await self.cbpi.fermenter.load_recipe(data, fermenterid, name)
async def clone(self, id, new_name):
recipe_path = os.path.join(".", 'config', "fermenterrecipes", "%s.yaml" % id)

View file

@ -20,7 +20,7 @@ class StepController:
self.cbpi = cbpi
self.logger = logging.getLogger(__name__)
self.path = os.path.join(".", 'config', "step_data.json")
self._loop = asyncio.get_event_loop()
#self._loop = asyncio.get_event_loop()
self.basic_data = {}
self.step = None
self.types = {}
@ -68,8 +68,9 @@ class StepController:
self.profile = list(map(lambda item: self.create(item), self.profile))
if startActive is True:
active_step = self.find_by_status("A")
if active_step is not None:
self._loop.create_task(self.start_step(active_step))
if active_step is not None:
asyncio.get_event_loop().create_task(self.start_step(active_step))
#self._loop.create_task(self.start_step(active_step))
async def add(self, item: Step):
logging.debug("Add step")

View file

@ -178,6 +178,8 @@ class SystemController:
mempercent = 0
eth0IP = "N/A"
wlan0IP = "N/A"
eth0speed = "N/A"
wlan0speed = "N/A"
TEMP_UNIT=self.cbpi.config.get("TEMP_UNIT", "C")
FAHRENHEIT = False if TEMP_UNIT == "C" else True
@ -225,12 +227,31 @@ class SystemController:
if str(addr.family) == "AddressFamily.AF_INET":
if addr.address:
wlan0IP = addr.address
info = psutil.net_if_stats()
try:
for nic in info:
if nic == 'eth0':
if info[nic].isup == True:
if info[nic].speed:
eth0speed = info[nic].speed
else:
eth0speed = "down"
if nic == 'wlan0':
if info[nic].isup == True:
ratestring = os.popen('iwlist wlan0 rate | grep Rate').read()
start = ratestring.find("=") + 1
end = ratestring.find(" Mb/s")
wlan0speed = ratestring[start:end]
else:
wlan0speed = "down"
except Exception as e:
logging.info(e)
except:
pass
if system == "Windows":
try:
ethernet = psutil.net_if_addrs()
ethernet = psutil.net_if_addrs()
for nic, addrs in ethernet.items():
if nic == "Ethernet":
for addr in addrs:
@ -242,6 +263,23 @@ class SystemController:
if str(addr.family) == "AddressFamily.AF_INET":
if addr.address:
wlan0IP = addr.address
info = psutil.net_if_stats()
try:
for nic in info:
if nic == 'Ethernet':
if info[nic].isup == True:
if info[nic].speed:
eth0speed = info[nic].speed
else:
eth0speed = "down"
if nic == 'WLAN':
if info[nic].isup == True:
if info[nic].speed:
wlan0speed = info[nic].speed
else:
wlan0speed = "down"
except Exception as e:
logging.info(e)
except:
pass
@ -258,7 +296,9 @@ class SystemController:
'temp': temp,
'temp_unit': TEMP_UNIT,
'eth0': eth0IP,
'wlan0': wlan0IP}
'wlan0': wlan0IP,
'eth0speed': eth0speed,
'wlan0speed': wlan0speed}
return systeminfo

View file

@ -1,5 +1,10 @@
import asyncio
import sys
try:
from asyncio import set_event_loop_policy, WindowsSelectorEventLoopPolicy
except ImportError:
pass
import json
from voluptuous.schema_builder import message
from cbpi.api.dataclasses import NotificationType
@ -82,6 +87,11 @@ async def error_middleware(request, handler):
class CraftBeerPi:
def __init__(self):
operationsystem= sys.platform
if operationsystem.startswith('win'):
set_event_loop_policy(WindowsSelectorEventLoopPolicy())
self.path = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1]) # The path to the package dir
self.version = __version__

View file

@ -32,8 +32,9 @@ class FermenterNotificationStep(CBPiFermentationStep):
if self.AutoNext == True:
self.cbpi.notify(self.name, self.props.get("Notification",""), NotificationType.INFO)
await self.next(self.fermenter.id)
return StepResult.DONE
if self.shutdown != True:
await self.next(self.fermenter.id)
return StepResult.DONE
else:
self.cbpi.notify(self.name, self.props.get("Notification",""), NotificationType.INFO, action=[NotificationAction("Next Step", self.NextStep)])
await self.push_update()
@ -42,6 +43,7 @@ class FermenterNotificationStep(CBPiFermentationStep):
await self.push_update()
async def on_start(self):
self.shutdown = False
self.summary=""
self.AutoNext = False if self.props.get("AutoNext", "No") == "No" else True
if self.timer is None:
@ -69,13 +71,12 @@ class FermenterNotificationStep(CBPiFermentationStep):
class FermenterTargetTempStep(CBPiFermentationStep):
async def NextStep(self, **kwargs):
await self.next(self.fermenter.id)
return StepResult.DONE
if self.shutdown != True:
await self.next(self.fermenter.id)
return StepResult.DONE
async def on_timer_done(self,timer):
self.summary = ""
#self.fermenter.target_temp = 0
await self.push_update()
if self.AutoMode == True:
await self.setAutoMode(False)
@ -88,10 +89,10 @@ class FermenterTargetTempStep(CBPiFermentationStep):
await self.push_update()
async def on_start(self):
self.shutdown = 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")
if self.fermenter is not None:
self.fermenter.target_temp = int(self.props.get("Temp", 0))
self.fermenter.target_temp = float(self.props.get("Temp", 0))
if self.AutoMode == True:
await self.setAutoMode(True)
self.summary = "Waiting for Target Temp"
@ -107,6 +108,9 @@ class FermenterTargetTempStep(CBPiFermentationStep):
await self.push_update()
async def run(self):
while self.get_sensor_value(self.props.get("Sensor", None)).get("value") > 900:
await asyncio.sleep(1)
self.starttemp= self.get_sensor_value(self.props.get("Sensor", None)).get("value")
if self.fermenter.target_temp >= self.starttemp:
logging.info("warmup")
while self.running == True:
@ -128,6 +132,7 @@ class FermenterTargetTempStep(CBPiFermentationStep):
async def reset(self):
self.timer = Timer(1 ,on_update=self.on_timer_update, on_done=self.on_timer_done)
self.timer.is_running == False
async def setAutoMode(self, auto_state):
try:
@ -162,13 +167,15 @@ class FermenterStep(CBPiFermentationStep):
else:
self.cbpi.notify(self.name, 'Timer is already running', NotificationType.WARNING)
#@action("Add 5 Minutes to Timer", [])
#async def add_timer(self):
# if self.timer.is_running == True:
# self.cbpi.notify(self.name, '5 Minutes added', NotificationType.INFO)
# await self.timer.add(300)
# else:
# self.cbpi.notify(self.name, 'Timer must be running to add time', NotificationType.WARNING)
# @action("Add 1 Day to Timer", [])
# async def add_timer(self):
# if self.timer.is_running == True:
# self.cbpi.notify(self.name, '1 Day added', NotificationType.INFO)
# await self.timer.add(86400)
# self.endtime = self.endtime +86400
# await self.update_endtime()
# else:
# self.cbpi.notify(self.name, 'Timer must be running to add time', NotificationType.WARNING)
async def on_timer_done(self,timer):
@ -176,8 +183,9 @@ class FermenterStep(CBPiFermentationStep):
if self.AutoMode == True:
await self.setAutoMode(False)
self.cbpi.notify(self.name, 'Step finished', NotificationType.SUCCESS)
await self.next(self.fermenter.id)
return StepResult.DONE
if self.shutdown != True:
await self.next(self.fermenter.id)
return StepResult.DONE
async def on_timer_update(self,timer, seconds):
@ -185,7 +193,8 @@ class FermenterStep(CBPiFermentationStep):
await self.push_update()
async def on_start(self):
if self.endtime == 0:
self.shutdown = False
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))
@ -194,9 +203,8 @@ class FermenterStep(CBPiFermentationStep):
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")
if self.fermenter is not None:
self.fermenter.target_temp = int(self.props.get("Temp", 0))
self.fermenter.target_temp = float(self.props.get("Temp", 0))
if self.AutoMode == True:
await self.setAutoMode(True)
await self.push_update()
@ -217,6 +225,9 @@ class FermenterStep(CBPiFermentationStep):
if self.endtime != 0 and self.timer is not None and self.timer.is_running == False:
self.timer.start()
self.timer.is_running = True
estimated_completion_time = datetime.fromtimestamp(time.time()+ self.fermentationtime)
self.cbpi.notify(self.name, 'Timer restarted. Estimated completion: {}'.format(estimated_completion_time.strftime("%d.%m, %H:%M")), NotificationType.INFO)
self.summary = "Waiting for Target Temp"
await self.push_update()
@ -229,17 +240,19 @@ 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
await self.update_endtime()
self.timer.is_running == False
async def run(self):
while self.get_sensor_value(self.props.get("Sensor", None)).get("value") > 900:
await asyncio.sleep(1)
self.starttemp= self.get_sensor_value(self.props.get("Sensor", None)).get("value")
if self.fermenter.target_temp >= self.starttemp:
logging.info("warmup")
while self.running == True:
@ -278,43 +291,6 @@ class FermenterStep(CBPiFermentationStep):
except Exception as e:
logging.error("Failed to switch on FermenterLogic {} {}".format(self.fermenter.id, e))
@parameters([Property.Number(label="TimerD", description="Timer Days", configurable=True),
Property.Number(label="TimerH", description="Timer Hours", configurable=True),
Property.Number(label="TimerM", description="Timer Minutes", configurable=True)
])
class FermenterWaitStep(CBPiFermentationStep):
async def on_timer_done(self, timer):
self.summary = ""
await self.next(self.fermenter.id)
return StepResult.DONE
async def on_timer_update(self, timer, seconds):
self.summary = Timer.format_time(seconds)
await self.push_update()
async def on_start(self):
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.timer is None:
self.timer = Timer(self.fermentationtime, on_update=self.on_timer_update, on_done=self.on_timer_done)
self.timer.start()
async def on_stop(self):
await self.timer.stop()
self.summary = ""
await self.push_update()
async def reset(self):
self.timer = Timer(self.fermentationtime, on_update=self.on_timer_update, on_done=self.on_timer_done)
async def run(self):
while self.running == True:
await asyncio.sleep(1)
return StepResult.DONE
def setup(cbpi):
'''
@ -328,4 +304,3 @@ def setup(cbpi):
cbpi.plugin.register("FermenterNotificationStep", FermenterNotificationStep)
cbpi.plugin.register("FermenterTargetTempStep", FermenterTargetTempStep)
cbpi.plugin.register("FermenterStep", FermenterStep)
#cbpi.plugin.register("FermenterWaitStep", FermenterWaitStep)

View file

@ -33,7 +33,7 @@ class FermenterAutostart(CBPiExtension):
try:
if (self.fermenter.instance is None or self.fermenter.instance.state == False):
await self.cbpi.fermenter.start(self.fermenter.id)
logging.info("Successfully switched on Fermenterlogic for Fermenter {}".format(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))
except:

View file

@ -10,7 +10,7 @@ logger = logging.getLogger(__name__)
try:
import RPi.GPIO as GPIO
except Exception:
logger.warning("Failed to load RPi.GPIO. Using Mock")
logger.warning("Failed to load RPi.GPIO. Using Mock instead")
MockRPi = MagicMock()
modules = {
"RPi": MockRPi,

View file

@ -22,6 +22,8 @@ class MQTTActor(CBPiActor):
async def on_start(self):
self.topic = self.props.get("Topic", None)
self.power = 100
await self.off()
self.state = False
async def on(self, power=None):
if power is not None:

View file

@ -18,7 +18,7 @@ class MQTTSensor(CBPiSensor):
if self.payload_text != None:
self.payload_text = self.payload_text.split('.')
self.mqtt_task = self.cbpi.satellite.subcribe(self.Topic, self.on_message)
self.value: int = 0
self.value: float = 999
async def on_message(self, message):
val = json.loads(message)

View file

@ -313,8 +313,8 @@ class FermentationHttpEndpoints():
data = await request.json()
fermenterid= request.match_info['id']
newstep = {"name": data.get("name"), "props": data.get("props", {}), "type": data.get("type")}
response_data = await self.controller.create_step(fermenterid,newstep)
newstep = {"name": data.get("name"), "props": data.get("props", {}), "endtime": 0, "type": data.get("type")}
response_data = await self.controller.add_step(fermenterid,newstep)
return web.json_response(data=response_data.to_dict())
@request_mapping(path="/{fermenterid}/{stepid}", method="PUT", auth_required=False)
@ -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)

View file

@ -117,7 +117,7 @@ class FermenterRecipeHttpEndpoints():
await self.controller.remove(name)
return web.Response(status=204)
@request_mapping(path="/{name}/{fermenterid}/brew", method="POST", auth_required=False)
@request_mapping(path="/{recipeid}/{fermenterid}/{name}/brew", method="POST", auth_required=False)
async def http_brew(self, request):
"""
@ -137,9 +137,10 @@ class FermenterRecipeHttpEndpoints():
"200":
description: successful operation
"""
recipeid = request.match_info['recipeid']
name = request.match_info['name']
fermenterid = request.match_info['fermenterid']
await self.controller.brew(name,fermenterid)
await self.controller.brew(recipeid,fermenterid,name)
return web.Response(status=204)
@request_mapping(path="/{id}/clone", method="POST", auth_required=False)

View file

@ -1,24 +1,24 @@
aiohttp==3.7.4
aiohttp==3.8.1
aiohttp-auth==0.1.1
aiohttp-route-decorator==0.1.4
aiohttp-security==0.4.0
aiohttp-session==2.9.0
aiohttp-swagger==1.0.15
aiojobs==0.3.0
aiosqlite==0.16.0
cryptography==3.3.2
requests==2.25.1
voluptuous==0.12.1
aiohttp-session==2.11.0
aiohttp-swagger==1.0.16
aiojobs==1.0.0
aiosqlite==0.17.0
cryptography==36.0.1
requests==2.27.1
voluptuous==0.12.2
pyfiglet==0.8.post1
pandas==1.4.0
shortuuid==1.0.1
tabulate==0.8.7
numpy==1.22.0
pandas==1.4.1
shortuuid==1.0.8
tabulate==0.8.9
numpy==1.22.2
cbpi4ui
click==7.1.2
importlib_metadata==4.8.2
click==8.0.4
importlib_metadata==4.11.1
asyncio-mqtt
psutil==5.8.0
psutil==5.9.0
zipp>=0.5
PyInquirer==1.0.3
colorama==0.4.4

View file

@ -27,34 +27,33 @@ setup(name='cbpi',
'': ['*.txt', '*.rst', '*.yaml'],
'cbpi': ['*','*.txt', '*.rst', '*.yaml']},
python_requires='>=3',
python_requires='>=3.9',
install_requires=[
"aiohttp==3.7.4",
"aiohttp==3.8.1",
"aiohttp-auth==0.1.1",
"aiohttp-route-decorator==0.1.4",
"aiohttp-security==0.4.0",
"aiohttp-session==2.9.0",
"aiohttp-swagger==1.0.15",
"aiojobs==0.3.0",
"aiosqlite==0.16.0",
"cryptography==3.3.2",
"requests==2.25.1",
"voluptuous==0.12.1",
"aiohttp-session==2.11.0",
"aiohttp-swagger==1.0.16",
"aiojobs==1.0.0 ",
"aiosqlite==0.17.0",
"cryptography==36.0.1",
"requests==2.27.1",
"voluptuous==0.12.2",
"pyfiglet==0.8.post1",
'click==7.1.2',
'shortuuid==1.0.1',
'tabulate==0.8.7',
'click==8.0.4',
'shortuuid==1.0.8',
'tabulate==0.8.9',
'asyncio-mqtt',
'psutil==5.8.0',
'colorama==0.4.4',
'PyInquirer==1.0.3',
'colorama==0.4.4',
'psutil==5.9.0',
'cbpi4ui',
'importlib_metadata'] + (
['RPi.GPIO==0.7.1'] if raspberrypi else [] ) +
(['numpy==1.22.0'] if (int(platform.python_version_tuple()[1]) >= 9) and (int(platform.python_version_tuple()[0]) == 3) else ['numpy==1.20.3'] ) +
(['pandas==1.4.0'] if (int(platform.python_version_tuple()[1]) >= 9) and (int(platform.python_version_tuple()[0]) == 3) else ['pandas==1.1.5'] ),
'importlib_metadata',
'numpy==1.22.2',
'pandas==1.4.1'] + (
['RPi.GPIO==0.7.1'] if raspberrypi else [] ),
dependency_links=[
'https://testpypi.python.org/pypi',