mirror of
https://github.com/PiBrewing/craftbeerpi4.git
synced 2024-11-25 08:28:23 +01:00
"mash profiles added"
This commit is contained in:
parent
ab14111787
commit
bd311edccd
19 changed files with 422 additions and 157 deletions
|
@ -1 +1 @@
|
|||
__version__ = "4.0.0.17"
|
||||
__version__ = "4.0.0.18"
|
|
@ -14,7 +14,8 @@ __all__ = ["CBPiActor",
|
|||
"SensorException",
|
||||
"ActorException",
|
||||
"CBPiSensor",
|
||||
"CBPiStep"]
|
||||
"CBPiStep",
|
||||
"Stop_Reason"]
|
||||
|
||||
from cbpi.api.actor import *
|
||||
from cbpi.api.sensor import *
|
||||
|
|
64
cbpi/api/base.py
Normal file
64
cbpi/api/base.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
from abc import abstractmethod, ABCMeta
|
||||
import asyncio
|
||||
from cbpi.api.config import ConfigType
|
||||
import time
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
class CBPiBase(metaclass=ABCMeta):
|
||||
|
||||
def get_static_config_value(self,name,default):
|
||||
return self.cbpi.static_config.get(name, default)
|
||||
|
||||
def get_config_value(self,name,default):
|
||||
return self.cbpi.config.get(name, default=default)
|
||||
|
||||
async def set_config_value(self,name,value):
|
||||
return await self.cbpi.config.set(name,value)
|
||||
|
||||
async def add_config_value(self, name, value, type: ConfigType, description, options=None):
|
||||
await self.cbpi.add(name, value, type, description, options=None)
|
||||
|
||||
def get_kettle(self,id):
|
||||
return self.cbpi.kettle.find_by_id(id)
|
||||
|
||||
async def set_target_temp(self,id, temp):
|
||||
await self.cbpi.kettle.set_target_temp(id, temp)
|
||||
|
||||
def get_sensor(self,id):
|
||||
return self.cbpi.sensor.find_by_id(id)
|
||||
|
||||
def get_sensor_value(self,id):
|
||||
return self.cbpi.sensor.get_sensor_value(id)
|
||||
|
||||
def get_actor(self,id):
|
||||
return self.cbpi.actor.find_by_id(id)
|
||||
|
||||
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):
|
||||
|
||||
try:
|
||||
print("\n\n ON\n\n\n\n" )
|
||||
await self.cbpi.actor.on(id)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
async def actor_off(self,id):
|
||||
try:
|
||||
print("\n\n OFF\n\n\n\n" )
|
||||
await self.cbpi.actor.off(id)
|
||||
except Exception as e:
|
||||
print("E", e)
|
||||
pass
|
||||
|
||||
|
|
@ -50,3 +50,5 @@ class CBPiExtension():
|
|||
except:
|
||||
logger.warning("Faild to load config %s/config.yaml" % path)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ from abc import abstractmethod, ABCMeta
|
|||
from cbpi.api.extension import CBPiExtension
|
||||
|
||||
from cbpi.api.config import ConfigType
|
||||
from cbpi.api.base import CBPiBase
|
||||
|
||||
|
||||
class CBPiSensor(metaclass=ABCMeta):
|
||||
class CBPiSensor(CBPiBase, metaclass=ABCMeta):
|
||||
|
||||
def __init__(self, cbpi, id, props):
|
||||
self.cbpi = cbpi
|
||||
|
@ -35,18 +35,6 @@ class CBPiSensor(metaclass=ABCMeta):
|
|||
def get_unit(self):
|
||||
pass
|
||||
|
||||
def get_static_config_value(self,name,default):
|
||||
return self.cbpi.static_config.get(name, default)
|
||||
|
||||
def get_config_value(self,name,default):
|
||||
return self.cbpi.config.get(name, default=default)
|
||||
|
||||
async def set_config_value(self,name,value):
|
||||
return await self.cbpi.config.set(name,value)
|
||||
|
||||
async def add_config_value(self, name, value, type: ConfigType, description, options=None):
|
||||
await self.cbpi.add(name, value, type, description, options=None)
|
||||
|
||||
def push_update(self, value):
|
||||
try:
|
||||
self.cbpi.ws.send(dict(topic="sensorstate", id=self.id, value=value))
|
||||
|
@ -57,5 +45,4 @@ class CBPiSensor(metaclass=ABCMeta):
|
|||
self.running = True
|
||||
|
||||
async def stop(self):
|
||||
|
||||
self.running = False
|
115
cbpi/api/step.py
115
cbpi/api/step.py
|
@ -5,8 +5,15 @@ import logging
|
|||
from abc import abstractmethod, ABCMeta
|
||||
import logging
|
||||
from cbpi.api.config import ConfigType
|
||||
from cbpi.api.base import CBPiBase
|
||||
from enum import Enum
|
||||
__all__ = ["Stop_Reason", "CBPiStep"]
|
||||
class Stop_Reason(Enum):
|
||||
STOP = 1
|
||||
NEXT = 2
|
||||
|
||||
class CBPiStep(metaclass=ABCMeta):
|
||||
|
||||
class CBPiStep(CBPiBase, metaclass=ABCMeta):
|
||||
def __init__(self, cbpi, id, name, props) :
|
||||
self.cbpi = cbpi
|
||||
self.props = {**props}
|
||||
|
@ -17,91 +24,61 @@ class CBPiStep(metaclass=ABCMeta):
|
|||
self.stop_reason = None
|
||||
self.pause = False
|
||||
self.task = None
|
||||
self._task = None
|
||||
self._exception_count = 0
|
||||
self._max_exceptions = 2
|
||||
self.state_msg = "No state"
|
||||
self.state_msg = ""
|
||||
|
||||
def get_state(self):
|
||||
return self.state_msg
|
||||
|
||||
def stop(self):
|
||||
self.stop_reason = "STOP"
|
||||
self.running = False
|
||||
|
||||
def start(self):
|
||||
self.running = True
|
||||
def push_update(self):
|
||||
self.cbpi.step.push_udpate()
|
||||
|
||||
async def stop(self):
|
||||
self.stop_reason = Stop_Reason.STOP
|
||||
self._task.cancel()
|
||||
await self._task
|
||||
|
||||
async def start(self):
|
||||
self.stop_reason = None
|
||||
|
||||
def next(self):
|
||||
self.stop_reason = "NEXT"
|
||||
self.running = False
|
||||
self._task = asyncio.create_task(self.run())
|
||||
self._task.add_done_callback(self.cbpi.step.done)
|
||||
|
||||
async def next(self):
|
||||
self.stop_reason = Stop_Reason.NEXT
|
||||
self._task.cancel()
|
||||
|
||||
async def reset(self):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def on_props_update(self, props):
|
||||
self.props = props
|
||||
|
||||
async def update(self, props):
|
||||
await self.cbpi.step.update_props(self.id, props)
|
||||
|
||||
async def run(self):
|
||||
while self.running:
|
||||
try:
|
||||
await self.execute()
|
||||
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)
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
await self.execute()
|
||||
except asyncio.CancelledError as e:
|
||||
raise e
|
||||
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)
|
||||
except asyncio.CancelledError as e:
|
||||
return self.id, self.stop_reason
|
||||
|
||||
|
||||
return (self.id, self.stop_reason)
|
||||
|
||||
|
||||
@abstractmethod
|
||||
async def execute(self):
|
||||
pass
|
||||
|
||||
|
||||
def get_static_config_value(self,name,default):
|
||||
return self.cbpi.static_config.get(name, default)
|
||||
|
||||
def get_config_value(self,name,default):
|
||||
return self.cbpi.config.get(name, default=default)
|
||||
|
||||
async def set_config_value(self,name,value):
|
||||
return await self.cbpi.config.set(name,value)
|
||||
|
||||
async def add_config_value(self, name, value, type: ConfigType, description, options=None):
|
||||
await self.cbpi.add(name, value, type, description, options=None)
|
||||
|
||||
def get_kettle(self,id):
|
||||
return self.cbpi.kettle.find_by_id(id)
|
||||
|
||||
async def set_target_temp(self,id, temp):
|
||||
await self.cbpi.kettle.set_target_temp(id, temp)
|
||||
|
||||
def get_sensor(self,id):
|
||||
return self.cbpi.sensor.find_by_id(id)
|
||||
|
||||
def get_actor(self,id):
|
||||
return self.cbpi.actor.find_by_id(id)
|
||||
|
||||
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):
|
||||
|
||||
try:
|
||||
await self.cbpi.actor.on(id)
|
||||
except:
|
||||
pass
|
||||
|
||||
async def actor_off(self,id):
|
||||
try:
|
||||
await self.cbpi.actor.off(id)
|
||||
except:
|
||||
pass
|
59
cbpi/api/timer.py
Normal file
59
cbpi/api/timer.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
import time
|
||||
import asyncio
|
||||
import math
|
||||
|
||||
|
||||
class Timer(object):
|
||||
|
||||
def __init__(self, timeout, callback, update = None) -> None:
|
||||
super().__init__()
|
||||
self.timeout = timeout
|
||||
self._timemout = self.timeout
|
||||
self._task = None
|
||||
self._callback = callback
|
||||
self._update = update
|
||||
self.start_time = None
|
||||
|
||||
async def _job(self):
|
||||
self.start_time = time.time()
|
||||
self.count = int(round(self._timemout, 0))
|
||||
try:
|
||||
for seconds in range(self.count, -1, -1):
|
||||
if self._update is not None:
|
||||
await self._update(seconds, self.format_time(seconds))
|
||||
await asyncio.sleep(1)
|
||||
self._callback()
|
||||
except asyncio.CancelledError:
|
||||
end = time.time()
|
||||
duration = end - self.start_time
|
||||
self._timemout = self._timemout - duration
|
||||
|
||||
def start(self):
|
||||
self._task = asyncio.create_task(self._job())
|
||||
|
||||
async def stop(self):
|
||||
self._task.cancel()
|
||||
await self._task
|
||||
|
||||
def reset(self):
|
||||
if self.is_running is True:
|
||||
return
|
||||
self._timemout = self.timeout
|
||||
|
||||
def is_running(self):
|
||||
return not self._task.done()
|
||||
|
||||
def set_time(self,timeout):
|
||||
if self.is_running is True:
|
||||
return
|
||||
self.timeout = timeout
|
||||
|
||||
def get_time(self):
|
||||
return self.format_time(int(round(self._timemout,0)))
|
||||
|
||||
def format_time(self, time):
|
||||
pattern = '{0:02d}:{1:02d}:{2:02d}'
|
||||
seconds = time % 60
|
||||
minutes = math.floor(time / 60) % 60
|
||||
hours = math.floor(time / 3600)
|
||||
return pattern.format(hours, minutes, seconds)
|
|
@ -12,6 +12,7 @@ class ActorController(BasicController):
|
|||
item = self.find_by_id(id)
|
||||
instance = item.get("instance")
|
||||
await instance.on()
|
||||
await self.push_udpate()
|
||||
except Exception as e:
|
||||
logging.error("Faild to switch on Actor {} {}".format(id, e))
|
||||
|
||||
|
@ -20,6 +21,7 @@ class ActorController(BasicController):
|
|||
item = self.find_by_id(id)
|
||||
instance = item.get("instance")
|
||||
await instance.off()
|
||||
await self.push_udpate()
|
||||
except Exception as e:
|
||||
logging.error("Faild to switch on Actor {} {}".format(id, e))
|
||||
|
||||
|
|
|
@ -9,10 +9,16 @@ class SensorController(BasicController):
|
|||
def create_dict(self, data):
|
||||
try:
|
||||
instance = data.get("instance")
|
||||
state = state=instance.get_state()
|
||||
state =instance.get_state()
|
||||
except Exception as e:
|
||||
logging.error("Faild to create sensor dict {} ".format(e))
|
||||
state = dict()
|
||||
|
||||
return dict(name=data.get("name"), id=data.get("id"), type=data.get("type"), state=state,props=data.get("props", []))
|
||||
|
||||
|
||||
def get_sensor_value(self, id):
|
||||
try:
|
||||
return self.find_by_id(id).get("instance").get_state()
|
||||
except Exception as e:
|
||||
logging.error("Faild read sensor value {} {} ".format(id, e))
|
||||
return None
|
|
@ -7,7 +7,7 @@ import shortuuid
|
|||
import logging
|
||||
import os.path
|
||||
|
||||
from ..api.step import CBPiStep
|
||||
from ..api.step import CBPiStep, Stop_Reason
|
||||
|
||||
|
||||
|
||||
|
@ -59,8 +59,15 @@ class StepController:
|
|||
|
||||
async def update(self, id, data):
|
||||
logging.info("update step")
|
||||
|
||||
self.profile = list(map(lambda old: {**old, **data} if old["id"] == id else old, self.profile))
|
||||
def merge_data(id, old, data):
|
||||
step = {**old, **data}
|
||||
try:
|
||||
step["instance"] = self.create_step(id,data["type"], data["name"], data["props"])
|
||||
except Exception as e:
|
||||
logging.error("Faild create step instance during update props")
|
||||
return step
|
||||
|
||||
self.profile = list(map(lambda old: {**merge_data(id, old, data)} if old["id"] == id else old, self.profile))
|
||||
await self.save()
|
||||
return self.find_by_id(id)
|
||||
|
||||
|
@ -69,7 +76,7 @@ class StepController:
|
|||
data = dict(basic=self.basic_data, profile=list(map(lambda x: dict(name=x["name"], type=x.get("type"), id=x["id"], status=x["status"],props=x["props"]), self.profile)))
|
||||
with open(self.path, "w") as file:
|
||||
json.dump(data, file, indent=4, sort_keys=True)
|
||||
await self.push_udpate()
|
||||
self.push_udpate()
|
||||
|
||||
async def start(self):
|
||||
# already running
|
||||
|
@ -88,7 +95,7 @@ class StepController:
|
|||
|
||||
step = self.find_by_status("I")
|
||||
if step is not None:
|
||||
logging.info("Start Step")
|
||||
logging.info("####### Start Step")
|
||||
|
||||
await self.start_step(step)
|
||||
await self.save()
|
||||
|
@ -102,9 +109,14 @@ class StepController:
|
|||
if step is not None:
|
||||
instance = step.get("instance")
|
||||
if instance is not None:
|
||||
logging.info("Next")
|
||||
instance.next()
|
||||
await instance.task
|
||||
await instance.next()
|
||||
step = self.find_by_status("P")
|
||||
if step is not None:
|
||||
instance = step.get("instance")
|
||||
if instance is not None:
|
||||
step["status"] = "D"
|
||||
await self.save()
|
||||
await self.start()
|
||||
else:
|
||||
logging.info("No Step is running")
|
||||
|
||||
|
@ -123,9 +135,7 @@ class StepController:
|
|||
if step != None and step.get("instance") is not None:
|
||||
logging.info("CALLING STOP STEP")
|
||||
instance = step.get("instance")
|
||||
instance.stop()
|
||||
# wait for task to be finished
|
||||
await instance.task
|
||||
await instance.stop()
|
||||
logging.info("STEP STOPPED")
|
||||
step["status"] = "P"
|
||||
await self.save()
|
||||
|
@ -139,10 +149,10 @@ class StepController:
|
|||
logging.info("Reset %s" % item.get("name"))
|
||||
item["status"] = "I"
|
||||
await item["instance"].reset()
|
||||
await self.push_udpate()
|
||||
self.push_udpate()
|
||||
|
||||
def create_step(self, id, type, name, props):
|
||||
|
||||
print(id, type, name, props)
|
||||
try:
|
||||
type_cfg = self.types.get(type)
|
||||
clazz = type_cfg.get("class")
|
||||
|
@ -169,7 +179,7 @@ class StepController:
|
|||
return
|
||||
self.profile[index], self.profile[index+direction] = self.profile[index+direction], self.profile[index]
|
||||
await self.save()
|
||||
await self.push_udpate()
|
||||
self.push_udpate()
|
||||
|
||||
async def delete(self, id):
|
||||
step = self.find_by_id(id)
|
||||
|
@ -188,22 +198,23 @@ class StepController:
|
|||
# Stopping all running task
|
||||
if instance.task != None and instance.task.done() is False:
|
||||
logging.info("Stop Step")
|
||||
instance.stop()
|
||||
await instance.stop()
|
||||
await instance.task
|
||||
await self.save()
|
||||
|
||||
def done(self, task):
|
||||
|
||||
id, reason = task.result()
|
||||
print("DONE", id, reason)
|
||||
if reason == "MAX_EXCEPTIONS":
|
||||
step_current = self.find_by_id(id)
|
||||
step_current["status"] = "E"
|
||||
self._loop.create_task(self.save())
|
||||
return
|
||||
|
||||
if reason == "NEXT":
|
||||
if reason == Stop_Reason.NEXT:
|
||||
step_current = self.find_by_status("A")
|
||||
if step_current is not None:
|
||||
|
||||
step_current["status"] = "D"
|
||||
async def wrapper():
|
||||
## TODO DONT CALL SAVE
|
||||
|
@ -221,25 +232,27 @@ class StepController:
|
|||
def get_index_by_id(self, id):
|
||||
return next((i for i, item in enumerate(self.profile) if item["id"] == id), None)
|
||||
|
||||
async def push_udpate(self):
|
||||
def push_udpate(self):
|
||||
self.cbpi.ws.send(dict(topic="step_update", data=list(map(lambda x: self.create_dict(x), self.profile))))
|
||||
|
||||
async def start_step(self,step):
|
||||
logging.info("Start Step")
|
||||
step.get("instance").start()
|
||||
step["instance"].task = self._loop.create_task(step["instance"].run())
|
||||
step["instance"].task .add_done_callback(self.done)
|
||||
try:
|
||||
await step["instance"].start()
|
||||
except Exception as e:
|
||||
print(".........",e)
|
||||
step["status"] = "A"
|
||||
print("STARTED",step)
|
||||
|
||||
async def update_props(self, id, props):
|
||||
logging.info("SAVE PROPS")
|
||||
step = self.find_by_id(id)
|
||||
step["props"] = props
|
||||
await self.save()
|
||||
await self.push_udpate()
|
||||
self.push_udpate()
|
||||
|
||||
async def save_basic(self, data):
|
||||
logging.info("SAVE Basic Data")
|
||||
self.basic_data = {**self.basic_data, **data,}
|
||||
await self.save()
|
||||
await self.push_udpate()
|
||||
self.push_udpate()
|
||||
|
|
|
@ -28,13 +28,10 @@ class CustomSensor(CBPiSensor):
|
|||
print("ACTION!", kwargs)
|
||||
|
||||
async def run(self):
|
||||
|
||||
|
||||
while self.running is True:
|
||||
print(self.get_config_value("TEMP_UNIT", "NONE"))
|
||||
print(self.get_static_config_value("port", "NONE"))
|
||||
await self.set_config_value("BREWERY_NAME", "WOOHOO HELLO")
|
||||
|
||||
self.value = random.randint(0,50)
|
||||
|
||||
self.value = random.randint(0,10)
|
||||
self.push_update(self.value)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
|
|
|
@ -1,31 +1,168 @@
|
|||
|
||||
import asyncio
|
||||
import time
|
||||
import random
|
||||
from cbpi.api.timer import Timer
|
||||
|
||||
from cbpi.api import *
|
||||
import logging
|
||||
|
||||
|
||||
@parameters([Property.Number(label="Timer", configurable=True),
|
||||
@parameters([Property.Number(label="Timer", description="Time in Minutes", configurable=True),
|
||||
Property.Number(label="Temp", configurable=True),
|
||||
Property.Sensor(label="Sensor"),
|
||||
Property.Kettle(label="Kettle")])
|
||||
class MashStep(CBPiStep):
|
||||
|
||||
def __init__(self, cbpi, id, name, props):
|
||||
super().__init__(cbpi, id, name, props)
|
||||
self.timer = None
|
||||
|
||||
def timer_done(self):
|
||||
self.state_msg = "Done"
|
||||
asyncio.create_task(self.next())
|
||||
|
||||
async def timer_update(self, seconds, time):
|
||||
self.state_msg = "{}".format(time)
|
||||
self.push_update()
|
||||
|
||||
def start_timer(self):
|
||||
if self.timer is None:
|
||||
self.time = int(self.props.get("Timer", 0))
|
||||
self.timer = Timer(self.time, self.timer_done, self.timer_update)
|
||||
self.timer.start()
|
||||
|
||||
async def stop_timer(self):
|
||||
if self.timer is not None:
|
||||
await self.timer.stop()
|
||||
self.state_msg = "{}".format(self.timer.get_time())
|
||||
|
||||
async def next(self):
|
||||
if self.timer is not None:
|
||||
await self.timer.stop()
|
||||
self.state_msg = ""
|
||||
await super().next()
|
||||
|
||||
async def stop(self):
|
||||
await super().stop()
|
||||
await self.stop_timer()
|
||||
|
||||
async def reset(self):
|
||||
self.state_msg = ""
|
||||
self.timer = None
|
||||
await super().reset()
|
||||
|
||||
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
|
||||
if self.timer is None:
|
||||
self.state_msg = "Waiting for Target Temp"
|
||||
self.push_update()
|
||||
else:
|
||||
if self.timer is not None and self.timer.is_running() is False:
|
||||
self.start_timer()
|
||||
sensor_value = 0
|
||||
|
||||
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
sensor_value = self.get_sensor_value(self.props.get("Sensor"))
|
||||
if sensor_value.get("value") >= 2 and self.timer == None:
|
||||
self.start_timer()
|
||||
|
||||
@parameters([Property.Number(label="Timer", description="Time in Minutes", configurable=True)])
|
||||
class WaitStep(CBPiStep):
|
||||
|
||||
def __init__(self, cbpi, id, name, props):
|
||||
super().__init__(cbpi, id, name, props)
|
||||
self.timer = None
|
||||
|
||||
def timer_done(self):
|
||||
self.state_msg = "Done"
|
||||
|
||||
asyncio.create_task(self.next())
|
||||
|
||||
async def timer_update(self, seconds, time):
|
||||
self.state_msg = "{}".format(time)
|
||||
self.push_update()
|
||||
|
||||
def start_timer(self):
|
||||
if self.timer is None:
|
||||
self.time = int(self.props.get("Timer", 0))
|
||||
self.timer = Timer(self.time, self.timer_done, self.timer_update)
|
||||
self.timer.start()
|
||||
|
||||
async def stop_timer(self):
|
||||
if self.timer is not None:
|
||||
await self.timer.stop()
|
||||
self.state_msg = "{}".format(self.timer.get_time())
|
||||
|
||||
async def next(self):
|
||||
if self.timer is not None:
|
||||
await self.timer.stop()
|
||||
self.state_msg = ""
|
||||
await super().next()
|
||||
|
||||
async def stop(self):
|
||||
await super().stop()
|
||||
await self.stop_timer()
|
||||
|
||||
async def reset(self):
|
||||
self.state_msg = ""
|
||||
self.timer = None
|
||||
await super().reset()
|
||||
|
||||
async def execute(self):
|
||||
self.start_timer()
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
|
||||
@parameters([Property.Number(label="Timer", description="Time in Seconds", configurable=True),
|
||||
Property.Actor(label="Actor")])
|
||||
class ActorStep(CBPiStep):
|
||||
|
||||
def __init__(self, cbpi, id, name, props):
|
||||
super().__init__(cbpi, id, name, props)
|
||||
self.timer = None
|
||||
|
||||
def timer_done(self):
|
||||
self.state_msg = "Done"
|
||||
asyncio.create_task(self.actor_off(self.actor_id))
|
||||
asyncio.create_task(self.next())
|
||||
|
||||
async def timer_update(self, seconds, time):
|
||||
self.state_msg = "{}".format(time)
|
||||
self.push_update()
|
||||
|
||||
def start_timer(self):
|
||||
if self.timer is None:
|
||||
self.time = int(self.props.get("Timer", 0))
|
||||
self.timer = Timer(self.time, self.timer_done, self.timer_update)
|
||||
self.timer.start()
|
||||
|
||||
async def stop_timer(self):
|
||||
if self.timer is not None:
|
||||
await self.timer.stop()
|
||||
self.state_msg = "{}".format(self.timer.get_time())
|
||||
|
||||
async def next(self):
|
||||
if self.timer is not None:
|
||||
await self.timer.stop()
|
||||
self.state_msg = ""
|
||||
await super().next()
|
||||
|
||||
async def stop(self):
|
||||
await super().stop()
|
||||
await self.actor_off(self.actor_id)
|
||||
await self.stop_timer()
|
||||
|
||||
async def reset(self):
|
||||
self.state_msg = ""
|
||||
self.timer = None
|
||||
await super().reset()
|
||||
|
||||
async def execute(self):
|
||||
self.start_timer()
|
||||
self.actor_id = self.props.get("Actor")
|
||||
await self.actor_on(self.actor_id)
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
|
||||
def setup(cbpi):
|
||||
'''
|
||||
This method is called by the server during startup
|
||||
|
@ -34,5 +171,8 @@ def setup(cbpi):
|
|||
:param cbpi: the cbpi core
|
||||
:return:
|
||||
'''
|
||||
|
||||
cbpi.plugin.register("ActorStep", ActorStep)
|
||||
cbpi.plugin.register("WaitStep", WaitStep)
|
||||
cbpi.plugin.register("MashStep", MashStep)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"data": [
|
||||
{
|
||||
"id": "YwGzXvWMpmbLb6XobesL8n",
|
||||
"name": "111",
|
||||
"name": "Actor 1",
|
||||
"props": {
|
||||
"GPIO": 4,
|
||||
"Inverted": "Yes"
|
||||
|
@ -12,7 +12,7 @@
|
|||
},
|
||||
{
|
||||
"id": "EsmZwWi9Qp3bzmXqq7N3Ly",
|
||||
"name": "HALO",
|
||||
"name": "Actor 2",
|
||||
"props": {
|
||||
"Frequency": "20",
|
||||
"GPIO": 5
|
||||
|
|
|
@ -102,18 +102,6 @@
|
|||
365,
|
||||
160
|
||||
],
|
||||
[
|
||||
285,
|
||||
175
|
||||
],
|
||||
[
|
||||
430,
|
||||
420
|
||||
],
|
||||
[
|
||||
240,
|
||||
350
|
||||
],
|
||||
[
|
||||
220,
|
||||
160
|
||||
|
|
|
@ -3,7 +3,7 @@ version: 4.0
|
|||
|
||||
index_url: /cbpi_ui/static/index.html
|
||||
plugins:
|
||||
- cbpi4-ui
|
||||
- cbpi4ui
|
||||
|
||||
port: 8080
|
||||
# login data
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"props": {},
|
||||
"sensor": "8ohkXvFA9UrkHLsxQL38wu",
|
||||
"state": {},
|
||||
"target_temp": 25,
|
||||
"target_temp": 45,
|
||||
"type": "CustomKettleLogic"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -11,6 +11,15 @@
|
|||
"value": 0
|
||||
},
|
||||
"type": "OneWire"
|
||||
},
|
||||
{
|
||||
"id": "JUGteK9KrSVPDxboWjBS4N",
|
||||
"name": "Test2",
|
||||
"props": {},
|
||||
"state": {
|
||||
"value": 0
|
||||
},
|
||||
"type": "CustomSensor"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -4,15 +4,27 @@
|
|||
},
|
||||
"profile": [
|
||||
{
|
||||
"id": "Gkjdsu45XPcfJimz4yHc4w",
|
||||
"name": "Test",
|
||||
"id": "SeL6hT9WxvA5yTsTakZuu8",
|
||||
"name": "Pump Left",
|
||||
"props": {
|
||||
"Kettle": "oHxKz3z5RjbsxfSz6KUgov",
|
||||
"Temp": "2",
|
||||
"Timer": "1"
|
||||
"Actor": "YwGzXvWMpmbLb6XobesL8n",
|
||||
"Timer": "5"
|
||||
},
|
||||
"status": "P",
|
||||
"type": "MashStep"
|
||||
"status": "D",
|
||||
"type": "ActorStep"
|
||||
},
|
||||
{
|
||||
"id": "YwyRyzA2ePiiXXnET5gEeH",
|
||||
"name": "Pump Right",
|
||||
"props": {
|
||||
"Actor": "EsmZwWi9Qp3bzmXqq7N3Ly",
|
||||
"Kettle": "oHxKz3z5RjbsxfSz6KUgov",
|
||||
"Sensor": "JUGteK9KrSVPDxboWjBS4N",
|
||||
"Temp": "2",
|
||||
"Timer": "5"
|
||||
},
|
||||
"status": "D",
|
||||
"type": "ActorStep"
|
||||
}
|
||||
]
|
||||
}
|
8
sample.py
Normal file
8
sample.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
import math
|
||||
|
||||
|
||||
|
||||
timerTime = 3661
|
||||
|
||||
|
||||
print(format_time(timerTime))
|
Loading…
Reference in a new issue