mirror of
https://github.com/PiBrewing/craftbeerpi4.git
synced 2024-12-22 13:34:55 +01:00
adding description
This commit is contained in:
parent
9938ce6de1
commit
3a39719957
17 changed files with 120 additions and 278 deletions
|
@ -1 +1 @@
|
|||
__version__ = "4.0.0.15"
|
||||
__version__ = "4.0.0.16"
|
|
@ -9,7 +9,6 @@ __all__ = ["CBPiActor",
|
|||
"parameters",
|
||||
"background_task",
|
||||
"CBPiKettleLogic",
|
||||
"CBPiSimpleStep",
|
||||
"CBPiException",
|
||||
"KettleException",
|
||||
"SensorException",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from abc import ABCMeta
|
||||
import asyncio
|
||||
from cbpi.api.extension import CBPiExtension
|
||||
from cbpi.api.config import ConfigType
|
||||
|
||||
__all__ = ["CBPiActor"]
|
||||
|
|
183
cbpi/api/step.py
183
cbpi/api/step.py
|
@ -4,11 +4,12 @@ import asyncio
|
|||
import logging
|
||||
from abc import abstractmethod, ABCMeta
|
||||
import logging
|
||||
from cbpi.api.config import ConfigType
|
||||
|
||||
class CBPiStep(metaclass=ABCMeta):
|
||||
def __init__(self, cbpi, id, name, props) :
|
||||
self.cbpi = cbpi
|
||||
self.props = {"wohoo": 0, "count": 5, **props}
|
||||
self.props = {**props}
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.status = 0
|
||||
|
@ -45,168 +46,62 @@ class CBPiStep(metaclass=ABCMeta):
|
|||
while self.running:
|
||||
try:
|
||||
await self.execute()
|
||||
except:
|
||||
except Exception as e:
|
||||
self._exception_count += 1
|
||||
logging.error("Step has thrown exception")
|
||||
if self._exception_count >= self._max_exceptions:
|
||||
self.stop_reason = "MAX_EXCEPTIONS"
|
||||
return (self.id, self.stop_reason)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
||||
return (self.id, self.stop_reason)
|
||||
|
||||
|
||||
@abstractmethod
|
||||
async def execute(self):
|
||||
pass
|
||||
|
||||
class CBPiSimpleStep(metaclass=ABCMeta):
|
||||
def get_static_config_value(self,name,default):
|
||||
return self.cbpi.static_config.get(name, default)
|
||||
|
||||
managed_fields = []
|
||||
def get_config_value(self,name,default):
|
||||
return self.cbpi.config.get(name, default=default)
|
||||
|
||||
def __init__(self, cbpi="", managed_fields=[], id="", name="", *args, **kwargs):
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self._exception_count = 0
|
||||
self._interval = 0.1
|
||||
self._max_exceptions = 2
|
||||
self.__dirty = False
|
||||
self.cbpi = cbpi
|
||||
self.id = id
|
||||
self.name = name
|
||||
async def set_config_value(self,name,value):
|
||||
return await self.cbpi.config.set(name,value)
|
||||
|
||||
if managed_fields:
|
||||
self.managed_fields = managed_fields
|
||||
for a in managed_fields:
|
||||
super(CBPiSimpleStep, self).__setattr__(a, kwargs.get(a, None))
|
||||
async def add_config_value(self, name, value, type: ConfigType, description, options=None):
|
||||
await self.cbpi.add(name, value, type, description, options=None)
|
||||
|
||||
self.is_stopped = False
|
||||
self.is_next = False
|
||||
self.start = time.time()
|
||||
def get_kettle(self,id):
|
||||
return self.cbpi.kettle.find_by_id(id)
|
||||
|
||||
self.logger.info(self.__repr__())
|
||||
async def set_target_temp(self,id, temp):
|
||||
await self.cbpi.kettle.set_target_temp(id, temp)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
mf = {}
|
||||
has_cbpi = True if self.cbpi is not None else False
|
||||
for f in self.managed_fields:
|
||||
mf[f] = super(CBPiSimpleStep, self).__getattribute__(f)
|
||||
return json.dumps(dict(type=self.__class__.__name__, id=self.id, name=self.name, has_link_to_cbpi=has_cbpi, managed_fields=mf))
|
||||
def get_sensor(self,id):
|
||||
return self.cbpi.sensor.find_by_id(id)
|
||||
|
||||
def get_status(self):
|
||||
pass
|
||||
def get_actor(self,id):
|
||||
return self.cbpi.actor.find_by_id(id)
|
||||
|
||||
def running(self):
|
||||
'''
|
||||
Method checks if the step should continue running.
|
||||
The method will return False if the step is requested to stop or the next step should start
|
||||
def get_actor_state(self,id):
|
||||
try:
|
||||
actor = self.cbpi.actor.find_by_id(id)
|
||||
return actor.get("instance").get_state()
|
||||
except:
|
||||
logging.error("Faild to read actor state in step - actor {}".format(id))
|
||||
return None
|
||||
|
||||
async def actor_on(self,id):
|
||||
|
||||
:return: True if the step is running. Otherwise False.
|
||||
'''
|
||||
if self.is_next is True:
|
||||
return False
|
||||
try:
|
||||
await self.cbpi.actor.on(id)
|
||||
except:
|
||||
pass
|
||||
|
||||
if self.is_stopped is True:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
async def run(self):
|
||||
|
||||
#while self.running():
|
||||
# print(".... Step %s ...." % self.id)
|
||||
# await asyncio.sleep(0.1)
|
||||
'''
|
||||
This method in running in the background. It invokes the run_cycle method in the configured interval
|
||||
It checks if a managed variable was modified in the last exection cycle. If yes, the method will persisit the new value of the
|
||||
managed property
|
||||
|
||||
:return: None
|
||||
'''
|
||||
|
||||
while self.running():
|
||||
|
||||
try:
|
||||
await self.run_cycle()
|
||||
except Exception as e:
|
||||
logging.exception("CBPiSimpleStep Error")
|
||||
self._exception_count = self._exception_count + 1
|
||||
if self._exception_count == self._max_exceptions:
|
||||
self.logger.error("Step Exception limit exceeded. Stopping Step")
|
||||
self.stop()
|
||||
|
||||
await asyncio.sleep(self._interval)
|
||||
|
||||
if self.is_dirty():
|
||||
# Now we have to store the managed props
|
||||
state = {}
|
||||
for field in self.managed_fields:
|
||||
|
||||
state[field] = self.__getattribute__(field)
|
||||
|
||||
await self.cbpi.step.model.update_step_state(self.id, state)
|
||||
await self.cbpi.bus.fire("step/update")
|
||||
self.reset_dirty()
|
||||
|
||||
|
||||
@abstractmethod
|
||||
async def run_cycle(self):
|
||||
'''
|
||||
This method is executed in the defined interval.
|
||||
That the place to put your step logic.
|
||||
The method need to be overwritten in the Ccstom step implementaion
|
||||
|
||||
:return: None
|
||||
'''
|
||||
|
||||
print("NOTING IMPLEMENTED")
|
||||
pass
|
||||
|
||||
def next(self):
|
||||
|
||||
'''
|
||||
Request to stop the the step
|
||||
|
||||
:return: None
|
||||
'''
|
||||
|
||||
self.is_next = True
|
||||
|
||||
def stop(self):
|
||||
'''
|
||||
Request to stop the step
|
||||
|
||||
:return: None
|
||||
'''
|
||||
self.is_stopped = True
|
||||
|
||||
def reset(self):
|
||||
'''
|
||||
Reset the step. This method needs to be overwritten by the custom step implementation
|
||||
|
||||
:return: None
|
||||
'''
|
||||
pass
|
||||
|
||||
def is_dirty(self):
|
||||
|
||||
'''
|
||||
Check if a managed variable has a new value
|
||||
|
||||
:return: True if at least one managed variable has a new value assigend. Otherwise False
|
||||
'''
|
||||
return self.__dirty
|
||||
|
||||
def reset_dirty(self):
|
||||
'''
|
||||
Reset the dirty flag
|
||||
|
||||
:return:
|
||||
'''
|
||||
|
||||
self.__dirty = False
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name != "_Step__dirty" and name in self.managed_fields:
|
||||
self.__dirty = True
|
||||
super(CBPiSimpleStep, self).__setattr__(name, value)
|
||||
else:
|
||||
super(CBPiSimpleStep, self).__setattr__(name, value)
|
||||
async def actor_off(self,id):
|
||||
try:
|
||||
await self.cbpi.actor.off(id)
|
||||
except:
|
||||
pass
|
|
@ -10,5 +10,5 @@ username: cbpi
|
|||
password: 123
|
||||
|
||||
plugins:
|
||||
- cbpi4-ui
|
||||
- cbpi4ui
|
||||
|
||||
|
|
|
@ -1,20 +1,8 @@
|
|||
{
|
||||
"basic": {
|
||||
"name": "WOOHOo"
|
||||
"name": ""
|
||||
},
|
||||
"profile": [
|
||||
{
|
||||
"id": "MSXuATqL56EAeCXrg3XLuY",
|
||||
"name": "Test",
|
||||
"props": {
|
||||
"Param1": 123,
|
||||
"Param2": "HALLO",
|
||||
"Param3": 1,
|
||||
"count": 6,
|
||||
"wohoo": 0
|
||||
},
|
||||
"status": "D",
|
||||
"type": "CustomStep2"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
|
@ -90,7 +90,6 @@ class BasicController:
|
|||
|
||||
type = item["type"]
|
||||
clazz = self.types[type]["class"]
|
||||
print("#####",item)
|
||||
item["instance"] = clazz(self.cbpi, item["id"], item["props"])
|
||||
await item["instance"].start()
|
||||
item["instance"].task = self._loop.create_task(item["instance"].run())
|
||||
|
|
|
@ -227,7 +227,7 @@ class StepController:
|
|||
async def start_step(self,step):
|
||||
logging.info("Start Step")
|
||||
step.get("instance").start()
|
||||
step["instance"].task = self._loop.create_task(step["instance"].run(), name=step["name"])
|
||||
step["instance"].task = self._loop.create_task(step["instance"].run())
|
||||
step["instance"].task .add_done_callback(self.done)
|
||||
step["status"] = "A"
|
||||
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
import asyncio
|
||||
import time
|
||||
|
||||
from cbpi.api import *
|
||||
|
||||
|
||||
@parameters([Property.Number(label="Param1", configurable=True),
|
||||
Property.Text(label="Param2", configurable=True, default_value="HALLO"),
|
||||
Property.Select(label="Param3", options=[1,2,4]),
|
||||
Property.Sensor(label="Param4"),
|
||||
Property.Actor(label="Param5")])
|
||||
class Step2(CBPiStep):
|
||||
|
||||
@action(key="name2", parameters=[])
|
||||
async def action2(self, **kwargs):
|
||||
print("CALL ACTION")
|
||||
|
||||
@action(key="name", parameters=[Property.Number(label="Test", configurable=True)])
|
||||
async def action(self, **kwargs):
|
||||
print("CALL ACTION")
|
||||
|
||||
async def execute(self):
|
||||
count = self.props.get("count", 0)
|
||||
self.state_msg = "COUNT %s" % count
|
||||
|
||||
self.props["count"] += 1
|
||||
await self.update(self.props)
|
||||
|
||||
if count >= 5:
|
||||
self.next()
|
||||
|
||||
async def reset(self):
|
||||
self.props["count"] = 0
|
||||
|
||||
def setup(cbpi):
|
||||
'''
|
||||
This method is called by the server during startup
|
||||
Here you need to register your plugins at the server
|
||||
|
||||
:param cbpi: the cbpi core
|
||||
:return:
|
||||
'''
|
||||
cbpi.plugin.register("CustomStep2", Step2)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
name: DummyStep
|
||||
version: 4
|
||||
active: true
|
|
@ -20,17 +20,17 @@ except Exception:
|
|||
import RPi.GPIO as GPIO
|
||||
|
||||
|
||||
@parameters([Property.Select(label="GPIO", options=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]), Property.Select(label="Inverted", options=["Yes", "No"])])
|
||||
@parameters([Property.Select(label="GPIO", description="The GPIO Pin", options=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]), Property.Select(label="Inverted", description="No: Active on high; Yes: Active on low", options=["Yes", "No"])])
|
||||
class GPIOActor(CBPiActor):
|
||||
|
||||
|
||||
def get_GPIO_state(self, state):
|
||||
# ON
|
||||
if state == 1:
|
||||
return 0 if self.inverted == False else 1
|
||||
return 1 if self.inverted == False else 0
|
||||
# OFF
|
||||
if state == 0:
|
||||
return 1 if self.inverted == False else 0
|
||||
return 0 if self.inverted == False else 1
|
||||
|
||||
async def start(self):
|
||||
await super().start()
|
||||
|
|
38
cbpi/extension/mashstep/__init__.py
Normal file
38
cbpi/extension/mashstep/__init__.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
import asyncio
|
||||
import time
|
||||
import random
|
||||
from cbpi.api import *
|
||||
|
||||
|
||||
@parameters([Property.Number(label="Timer", configurable=True),
|
||||
Property.Number(label="Temp", configurable=True),
|
||||
Property.Kettle(label="Kettle")])
|
||||
class MashStep(CBPiStep):
|
||||
|
||||
|
||||
async def execute(self):
|
||||
try:
|
||||
kid = self.props.get("Kettle", None)
|
||||
kettle = self.get_kettle(kid)
|
||||
actor = self.get_actor(kettle.get("heater"))
|
||||
print(self.get_actor_state(kettle.get("heater")))
|
||||
await self.cbpi.kettle.set_target_temp(kid, random.randint(0,50))
|
||||
if self.v is True:
|
||||
await self.actor_on(kettle.get("heater"))
|
||||
else:
|
||||
await self.actor_off(kettle.get("heater"))
|
||||
self.v = not self.v
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def setup(cbpi):
|
||||
'''
|
||||
This method is called by the server during startup
|
||||
Here you need to register your plugins at the server
|
||||
|
||||
:param cbpi: the cbpi core
|
||||
:return:
|
||||
'''
|
||||
cbpi.plugin.register("MashStep", MashStep)
|
||||
|
3
cbpi/extension/mashstep/config.yaml
Normal file
3
cbpi/extension/mashstep/config.yaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
name: MashStep
|
||||
version: 4
|
||||
active: true
|
|
@ -41,6 +41,29 @@
|
|||
"type": "ActorButton",
|
||||
"x": 505,
|
||||
"y": 140
|
||||
},
|
||||
{
|
||||
"id": "3cae292a-f12d-4c9e-8e0e-2fd93a9b253e",
|
||||
"name": "TargetTemp",
|
||||
"props": {
|
||||
"color": "#fff",
|
||||
"kettle": "oHxKz3z5RjbsxfSz6KUgov",
|
||||
"size": "12",
|
||||
"unit": "\u00b0"
|
||||
},
|
||||
"type": "TargetTemp",
|
||||
"x": 160,
|
||||
"y": 75
|
||||
},
|
||||
{
|
||||
"id": "bb90e1ab-7b2d-4623-8df3-3139f91b7087",
|
||||
"name": "Steps",
|
||||
"props": {
|
||||
"width": "200"
|
||||
},
|
||||
"type": "Steps",
|
||||
"x": 595,
|
||||
"y": 50
|
||||
}
|
||||
],
|
||||
"pathes": [
|
||||
|
|
|
@ -2,40 +2,13 @@
|
|||
"data": [
|
||||
{
|
||||
"agitator": "EsmZwWi9Qp3bzmXqq7N3Ly",
|
||||
"heater": "YwGzXvWMpmbLb6XobesL8n",
|
||||
"heater": "EsmZwWi9Qp3bzmXqq7N3Ly",
|
||||
"id": "oHxKz3z5RjbsxfSz6KUgov",
|
||||
"name": "MashTun",
|
||||
"props": {},
|
||||
"sensor": "8ohkXvFA9UrkHLsxQL38wu",
|
||||
"state": {},
|
||||
"target_temp": 52,
|
||||
"type": "CustomKettleLogic"
|
||||
},
|
||||
{
|
||||
"agitator": "",
|
||||
"heater": "",
|
||||
"id": "WxAkesrkqiHH3Gywc4fMci",
|
||||
"name": "HLT",
|
||||
"props": {
|
||||
"Param2": "13",
|
||||
"Param3": 1,
|
||||
"Param4": "",
|
||||
"Param5": "8BLRqagLicCdEBDdc77Sgr"
|
||||
},
|
||||
"sensor": "",
|
||||
"state": {},
|
||||
"target_temp": null,
|
||||
"type": ""
|
||||
},
|
||||
{
|
||||
"agitator": "",
|
||||
"heater": "NjammuygecdvMpoGYc3rXt",
|
||||
"id": "a7bWex85Z9Td4atwgazpXW",
|
||||
"name": "Boil",
|
||||
"props": {},
|
||||
"sensor": "",
|
||||
"state": {},
|
||||
"target_temp": 55,
|
||||
"target_temp": 25,
|
||||
"type": "CustomKettleLogic"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -4,43 +4,15 @@
|
|||
},
|
||||
"profile": [
|
||||
{
|
||||
"id": "T2y34Mbex9KjNWXhzfCRby",
|
||||
"name": "MashIn",
|
||||
"id": "Gkjdsu45XPcfJimz4yHc4w",
|
||||
"name": "Test",
|
||||
"props": {
|
||||
"Param1": 123,
|
||||
"Param2": "HALLO",
|
||||
"Param3": 1,
|
||||
"count": 1,
|
||||
"wohoo": 0
|
||||
"Kettle": "oHxKz3z5RjbsxfSz6KUgov",
|
||||
"Temp": "2",
|
||||
"Timer": "1"
|
||||
},
|
||||
"status": "P",
|
||||
"type": "CustomStep2"
|
||||
},
|
||||
{
|
||||
"id": "RjS8Zb2GGpUtNsqHsES3yF",
|
||||
"name": "Step2",
|
||||
"props": {
|
||||
"Param1": 123,
|
||||
"Param2": "HALLO",
|
||||
"Param3": 1,
|
||||
"count": 0,
|
||||
"wohoo": 0
|
||||
},
|
||||
"status": "I",
|
||||
"type": "CustomStep2"
|
||||
},
|
||||
{
|
||||
"id": "WkZG4fDNxZdtZ7uoTsSHhR",
|
||||
"name": "Mash Step 1",
|
||||
"props": {
|
||||
"Param1": 123,
|
||||
"Param2": "HALLO",
|
||||
"Param3": 1,
|
||||
"count": 0,
|
||||
"wohoo": 0
|
||||
},
|
||||
"status": "I",
|
||||
"type": "CustomStep2"
|
||||
"type": "MashStep"
|
||||
}
|
||||
]
|
||||
}
|
2
setup.py
2
setup.py
|
@ -32,7 +32,7 @@ setup(name='cbpi',
|
|||
'shortuuid==1.0.1',
|
||||
'tabulate==0.8.7',
|
||||
'asyncio-mqtt',
|
||||
'cbpi4-ui',
|
||||
'cbpi4ui',
|
||||
],
|
||||
dependency_links=[
|
||||
'https://testpypi.python.org/pypi',
|
||||
|
|
Loading…
Reference in a new issue