mirror of
https://github.com/PiBrewing/craftbeerpi4.git
synced 2024-11-25 08:28:23 +01:00
Merge pull request #4 from avollkopf/development
Merge from Development branch
This commit is contained in:
commit
a8cda4721b
9 changed files with 177 additions and 44 deletions
|
@ -1 +1 @@
|
||||||
__version__ = "4.0.0.42"
|
__version__ = "4.0.0.45"
|
||||||
|
|
|
@ -20,6 +20,7 @@ class CBPiActor(metaclass=ABCMeta):
|
||||||
self.data_logger = None
|
self.data_logger = None
|
||||||
self.state = False
|
self.state = False
|
||||||
self.running = False
|
self.running = False
|
||||||
|
self.power = 100
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
pass
|
pass
|
||||||
|
@ -87,5 +88,12 @@ class CBPiActor(metaclass=ABCMeta):
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
async def set_power(self,power):
|
||||||
|
'''
|
||||||
|
Code to set power for actor
|
||||||
|
|
||||||
|
:return: dict power
|
||||||
|
'''
|
||||||
|
return dict(power=self.power)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
|
@ -44,13 +44,13 @@ class CBPiBase(metaclass=ABCMeta):
|
||||||
actor = self.cbpi.actor.find_by_id(id)
|
actor = self.cbpi.actor.find_by_id(id)
|
||||||
return actor.get("instance").get_state()
|
return actor.get("instance").get_state()
|
||||||
except:
|
except:
|
||||||
logging.error("Faild to read actor state in step - actor {}".format(id))
|
logging.error("Failed to read actor state in step - actor {}".format(id))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def actor_on(self,id):
|
async def actor_on(self,id,power=100):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await self.cbpi.actor.on(id)
|
await self.cbpi.actor.on(id,power)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -60,4 +60,8 @@ class CBPiBase(metaclass=ABCMeta):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
async def actor_set_power(self,id,power):
|
||||||
|
try:
|
||||||
|
await self.cbpi.actor.set_power(id,power)
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
|
@ -55,13 +55,14 @@ class Actor:
|
||||||
name: str = None
|
name: str = None
|
||||||
props: Props = Props()
|
props: Props = Props()
|
||||||
state: bool = False
|
state: bool = False
|
||||||
|
power: int = 100
|
||||||
type: str = None
|
type: str = None
|
||||||
instance: str = None
|
instance: str = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "name={} props={}, state={}, type={}".format(self.name, self.props, self.state, self.type)
|
return "name={} props={}, state={}, type={}, power={}".format(self.name, self.props, self.state, self.type, self.power)
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return dict(id=self.id, name=self.name, type=self.type, props=self.props.to_dict(), state2="HELLO WORLD", state=self.instance.get_state())
|
return dict(id=self.id, name=self.name, type=self.type, props=self.props.to_dict(), state2="HELLO WORLD", state=self.instance.get_state(), power=self.power)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -8,16 +8,18 @@ class ActorController(BasicController):
|
||||||
super(ActorController, self).__init__(cbpi, Actor,"actor.json")
|
super(ActorController, self).__init__(cbpi, Actor,"actor.json")
|
||||||
self.update_key = "actorupdate"
|
self.update_key = "actorupdate"
|
||||||
|
|
||||||
async def on(self, id):
|
async def on(self, id, power=None):
|
||||||
try:
|
try:
|
||||||
item = self.find_by_id(id)
|
item = self.find_by_id(id)
|
||||||
if item.instance.state is False:
|
if item.instance.state is False:
|
||||||
await item.instance.on()
|
await item.instance.on(power)
|
||||||
await self.push_udpate()
|
await self.push_udpate()
|
||||||
self.cbpi.push_update("cbpi/actor/"+id, item.to_dict(), True)
|
self.cbpi.push_update("cbpi/actor/"+id, item.to_dict(), True)
|
||||||
|
else:
|
||||||
|
await self.set_power(id, power)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("Faild to switch on Actor {} {}".format(id, e))
|
logging.error("Failed to switch on Actor {} {}".format(id, e))
|
||||||
|
|
||||||
async def off(self, id):
|
async def off(self, id):
|
||||||
try:
|
try:
|
||||||
|
@ -27,7 +29,7 @@ class ActorController(BasicController):
|
||||||
await self.push_udpate()
|
await self.push_udpate()
|
||||||
self.cbpi.push_update("cbpi/actor/"+id, item.to_dict())
|
self.cbpi.push_update("cbpi/actor/"+id, item.to_dict())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("Faild to switch on Actor {} {}".format(id, e), True)
|
logging.error("Failed to switch on Actor {} {}".format(id, e), True)
|
||||||
|
|
||||||
async def toogle(self, id):
|
async def toogle(self, id):
|
||||||
try:
|
try:
|
||||||
|
@ -36,5 +38,20 @@ class ActorController(BasicController):
|
||||||
await instance.toggle()
|
await instance.toggle()
|
||||||
self.cbpi.push_update("cbpi/actor/update", item.to_dict())
|
self.cbpi.push_update("cbpi/actor/update", item.to_dict())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("Faild to switch on Actor {} {}".format(id, e))
|
logging.error("Failed to toggle Actor {} {}".format(id, e))
|
||||||
|
|
||||||
|
async def set_power(self, id, power):
|
||||||
|
try:
|
||||||
|
item = self.find_by_id(id)
|
||||||
|
await item.instance.set_power(power)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error("Failed to set power {} {}".format(id, e))
|
||||||
|
|
||||||
|
async def actor_update(self, id, power):
|
||||||
|
try:
|
||||||
|
item = self.find_by_id(id)
|
||||||
|
item.power = round(power)
|
||||||
|
await self.push_udpate()
|
||||||
|
self.cbpi.push_update("cbpi/actor/"+id, item.to_dict())
|
||||||
|
except Exception as e:
|
||||||
|
logging.error("Failed to update Actor {} {}".format(id, e))
|
||||||
|
|
|
@ -85,6 +85,31 @@ class SystemController:
|
||||||
else:
|
else:
|
||||||
self.cbpi.notify("Error", "Wrong content type. Upload failed", NotificationType.ERROR)
|
self.cbpi.notify("Error", "Wrong content type. Upload failed", NotificationType.ERROR)
|
||||||
|
|
||||||
|
async def uploadSVG(self, data):
|
||||||
|
fileData = data['File']
|
||||||
|
filename = fileData.filename
|
||||||
|
svg_file = fileData.file
|
||||||
|
content_type = fileData.content_type
|
||||||
|
|
||||||
|
logging.info(content_type)
|
||||||
|
|
||||||
|
if content_type == 'image/svg+xml':
|
||||||
|
try:
|
||||||
|
content = svg_file.read().decode('utf-8','replace')
|
||||||
|
if svg_file and self.allowed_file(filename, 'svg'):
|
||||||
|
self.path = os.path.join(".","config","dashboard","widgets", filename)
|
||||||
|
logging.info(self.path)
|
||||||
|
|
||||||
|
f=open(self.path, "w")
|
||||||
|
f.write(content)
|
||||||
|
f.close()
|
||||||
|
self.cbpi.notify("Success", "SVG file ({}) has been uploaded.".format(filename), NotificationType.SUCCESS)
|
||||||
|
except:
|
||||||
|
self.cbpi.notify("Error", "SVG upload failed", NotificationType.ERROR)
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.cbpi.notify("Error", "Wrong content type. Upload failed", NotificationType.ERROR)
|
||||||
|
|
||||||
async def systeminfo(self):
|
async def systeminfo(self):
|
||||||
logging.info("SYSTEMINFO")
|
logging.info("SYSTEMINFO")
|
||||||
system = ""
|
system = ""
|
||||||
|
@ -147,6 +172,23 @@ class SystemController:
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if system == "Windows":
|
||||||
|
try:
|
||||||
|
ethernet = psutil.net_if_addrs()
|
||||||
|
for nic, addrs in ethernet.items():
|
||||||
|
if nic == "Ethernet":
|
||||||
|
for addr in addrs:
|
||||||
|
if str(addr.family) == "AddressFamily.AF_INET":
|
||||||
|
if addr.address:
|
||||||
|
eth0IP = addr.address
|
||||||
|
if nic == "WLAN":
|
||||||
|
for addr in addrs:
|
||||||
|
if str(addr.family) == "AddressFamily.AF_INET":
|
||||||
|
if addr.address:
|
||||||
|
wlan0IP = addr.address
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,8 @@ class CraftBeerPi:
|
||||||
policy = auth.SessionTktAuthentication(urandom(32), 60, include_ip=True)
|
policy = auth.SessionTktAuthentication(urandom(32), 60, include_ip=True)
|
||||||
middlewares = [web.normalize_path_middleware(), session_middleware(EncryptedCookieStorage(urandom(32))),
|
middlewares = [web.normalize_path_middleware(), session_middleware(EncryptedCookieStorage(urandom(32))),
|
||||||
auth.auth_middleware(policy), error_middleware]
|
auth.auth_middleware(policy), error_middleware]
|
||||||
self.app = web.Application(middlewares=middlewares)
|
# max upload size increased to 5 Mb. Default is 1 Mb -> config and svg upload
|
||||||
|
self.app = web.Application(middlewares=middlewares, client_max_size=5*1024*1024)
|
||||||
self.app["cbpi"] = self
|
self.app["cbpi"] = self
|
||||||
|
|
||||||
self._setup_shutdownhook()
|
self._setup_shutdownhook()
|
||||||
|
|
|
@ -24,18 +24,20 @@ mode = GPIO.getmode()
|
||||||
if (mode == None):
|
if (mode == None):
|
||||||
GPIO.setmode(GPIO.BCM)
|
GPIO.setmode(GPIO.BCM)
|
||||||
|
|
||||||
@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"],description="No: Active on high; Yes: Active on low")])
|
@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"],description="No: Active on high; Yes: Active on low"),
|
||||||
|
Property.Select(label="SamplingTime", options=[2,5],description="Time in seconds for power base interval (Default:5)")])
|
||||||
class GPIOActor(CBPiActor):
|
class GPIOActor(CBPiActor):
|
||||||
|
|
||||||
@action(key="Cusotm Action", parameters=[Property.Number("Value", configurable=True), Property.Kettle("Kettle")])
|
# Custom property which can be configured by the user
|
||||||
async def custom_action(self, **kwargs):
|
@action("Set Power", parameters=[Property.Number(label="Power", configurable=True,description="Power Setting [0-100]")])
|
||||||
print("ACTION", kwargs)
|
async def setpower(self,Power = 100 ,**kwargs):
|
||||||
|
self.power=int(Power)
|
||||||
|
if self.power < 0:
|
||||||
@action(key="Cusotm Action2", parameters=[Property.Number("Value", configurable=True)])
|
self.power = 0
|
||||||
async def custom_action2(self, **kwargs):
|
if self.power > 100:
|
||||||
print("ACTION2")
|
self.power = 100
|
||||||
|
await self.set_power(self.power)
|
||||||
|
|
||||||
def get_GPIO_state(self, state):
|
def get_GPIO_state(self, state):
|
||||||
# ON
|
# ON
|
||||||
|
@ -46,13 +48,19 @@ class GPIOActor(CBPiActor):
|
||||||
return 0 if self.inverted == False else 1
|
return 0 if self.inverted == False else 1
|
||||||
|
|
||||||
async def on_start(self):
|
async def on_start(self):
|
||||||
|
self.power = 100
|
||||||
self.gpio = self.props.GPIO
|
self.gpio = self.props.GPIO
|
||||||
self.inverted = True if self.props.get("Inverted", "No") == "Yes" else False
|
self.inverted = True if self.props.get("Inverted", "No") == "Yes" else False
|
||||||
|
self.sampleTime = int(self.props.get("SamplingTime", 5))
|
||||||
GPIO.setup(self.gpio, GPIO.OUT)
|
GPIO.setup(self.gpio, GPIO.OUT)
|
||||||
GPIO.output(self.gpio, self.get_GPIO_state(0))
|
GPIO.output(self.gpio, self.get_GPIO_state(0))
|
||||||
self.state = False
|
self.state = False
|
||||||
|
|
||||||
async def on(self, power=0):
|
async def on(self, power = None):
|
||||||
|
if power is not None:
|
||||||
|
self.power = power
|
||||||
|
await self.set_power(self.power)
|
||||||
|
|
||||||
logger.info("ACTOR %s ON - GPIO %s " % (self.id, self.gpio))
|
logger.info("ACTOR %s ON - GPIO %s " % (self.id, self.gpio))
|
||||||
GPIO.output(self.gpio, self.get_GPIO_state(1))
|
GPIO.output(self.gpio, self.get_GPIO_state(1))
|
||||||
self.state = True
|
self.state = True
|
||||||
|
@ -67,46 +75,81 @@ class GPIOActor(CBPiActor):
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
while self.running == True:
|
while self.running == True:
|
||||||
await asyncio.sleep(1)
|
if self.state == True:
|
||||||
|
heating_time=self.sampleTime * (self.power / 100)
|
||||||
|
wait_time=self.sampleTime - heating_time
|
||||||
|
if heating_time > 0:
|
||||||
|
#logging.info("Heating Time: {}".format(heating_time))
|
||||||
|
GPIO.output(self.gpio, self.get_GPIO_state(1))
|
||||||
|
await asyncio.sleep(heating_time)
|
||||||
|
if wait_time > 0:
|
||||||
|
#logging.info("Wait Time: {}".format(wait_time))
|
||||||
|
GPIO.output(self.gpio, self.get_GPIO_state(0))
|
||||||
|
await asyncio.sleep(wait_time)
|
||||||
|
else:
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
async def set_power(self, power):
|
||||||
|
self.power = power
|
||||||
|
await self.cbpi.actor.actor_update(self.id,power)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@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.Number("Frequency", configurable=True)])
|
@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.Number(label="Frequency", configurable=True)])
|
||||||
class GPIOPWMActor(CBPiActor):
|
class GPIOPWMActor(CBPiActor):
|
||||||
|
|
||||||
# Custom property which can be configured by the user
|
# Custom property which can be configured by the user
|
||||||
@action("test", parameters={})
|
@action("Set Power", parameters=[Property.Number(label="Power", configurable=True,description="Power Setting [0-100]")])
|
||||||
async def power(self, **kwargs):
|
async def setpower(self,Power = 100 ,**kwargs):
|
||||||
self.p.ChangeDutyCycle(1)
|
logging.info(Power)
|
||||||
|
self.power=int(Power)
|
||||||
|
if self.power < 0:
|
||||||
|
self.power = 0
|
||||||
|
if self.power > 100:
|
||||||
|
self.power = 100
|
||||||
|
await self.set_power(self.power)
|
||||||
|
|
||||||
async def start(self):
|
async def on_start(self):
|
||||||
await super().start()
|
self.gpio = self.props.get("GPIO", None)
|
||||||
self.gpio = self.props.get("GPIO")
|
self.frequency = self.props.get("Frequency", 0.5)
|
||||||
self.frequency = self.props.get("Frequency")
|
if self.gpio is not None:
|
||||||
GPIO.setup(self.gpio, GPIO.OUT)
|
GPIO.setup(self.gpio, GPIO.OUT)
|
||||||
GPIO.output(self.gpio, 0)
|
GPIO.output(self.gpio, 0)
|
||||||
self.state = False
|
self.state = False
|
||||||
|
self.power = 100
|
||||||
|
self.p = None
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def on(self, power=0):
|
async def on(self, power = None):
|
||||||
logger.info("PWM ACTOR %s ON - GPIO %s " % (self.id, self.gpio))
|
if power is not None:
|
||||||
|
self.power = power
|
||||||
|
|
||||||
|
logger.info("PWM ACTOR %s ON - GPIO %s - Frequency %s - Power %s" % (self.id, self.gpio,self.frequency,self.power))
|
||||||
try:
|
try:
|
||||||
self.p = GPIO.PWM(int(self.gpio), float(self.frequency))
|
if self.p is None:
|
||||||
self.p.start(1)
|
self.p = GPIO.PWM(int(self.gpio), float(self.frequency))
|
||||||
|
self.p.start(self.power)
|
||||||
|
self.state = True
|
||||||
|
await self.cbpi.actor.actor_update(self.id,self.power)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
self.state = True
|
|
||||||
|
|
||||||
async def off(self):
|
async def off(self):
|
||||||
logger.info("PWM ACTOR %s OFF - GPIO %s " % (self.id, self.gpio))
|
logger.info("PWM ACTOR %s OFF - GPIO %s " % (self.id, self.gpio))
|
||||||
self.p.stop()
|
self.p.ChangeDutyCycle(0)
|
||||||
self.state = False
|
self.state = False
|
||||||
|
|
||||||
|
async def set_power(self, power):
|
||||||
|
if self.p and self.state == True:
|
||||||
|
self.p.ChangeDutyCycle(power)
|
||||||
|
await self.cbpi.actor.actor_update(self.id,power)
|
||||||
|
pass
|
||||||
|
|
||||||
def get_state(self):
|
def get_state(self):
|
||||||
return self.state
|
return self.state
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
while self.running == True:
|
while self.running == True:
|
||||||
|
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
def setup(cbpi):
|
def setup(cbpi):
|
||||||
|
|
|
@ -176,3 +176,20 @@ class SystemHttpEndpoints:
|
||||||
"""
|
"""
|
||||||
systeminfo = await self.controller.systeminfo()
|
systeminfo = await self.controller.systeminfo()
|
||||||
return web.json_response(data=systeminfo)
|
return web.json_response(data=systeminfo)
|
||||||
|
|
||||||
|
@request_mapping("/uploadsvg", method="POST", name="UploadSVG", auth_required=False)
|
||||||
|
async def uploadSVG(self, request):
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
description: Upload SVG file to widgets folder
|
||||||
|
tags:
|
||||||
|
- System
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: successful operation
|
||||||
|
"""
|
||||||
|
logging.info("Upload SVG file")
|
||||||
|
data = await request.post()
|
||||||
|
logging.info("Data received")
|
||||||
|
await self.controller.uploadSVG(data)
|
||||||
|
return web.Response(status=200)
|
Loading…
Reference in a new issue