mirror of
https://github.com/PiBrewing/craftbeerpi4.git
synced 2024-11-23 15:38:14 +01:00
189 lines
6.5 KiB
Python
189 lines
6.5 KiB
Python
import asyncio
|
|
import logging
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from cbpi.api import *
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
try:
|
|
import RPi.GPIO as GPIO
|
|
except Exception:
|
|
logger.warning("Failed to load RPi.GPIO. Using Mock instead")
|
|
MockRPi = MagicMock()
|
|
modules = {
|
|
"RPi": MockRPi,
|
|
"RPi.GPIO": MockRPi.GPIO
|
|
}
|
|
patcher = patch.dict("sys.modules", modules)
|
|
patcher.start()
|
|
import RPi.GPIO as GPIO
|
|
|
|
mode = GPIO.getmode()
|
|
if (mode == None):
|
|
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"),
|
|
Property.Select(label="SamplingTime", options=[2,5],description="Time in seconds for power base interval (Default:5)")])
|
|
class GPIOActor(CBPiActor):
|
|
|
|
# Custom property which can be configured by the user
|
|
@action("Set Power", parameters=[Property.Number(label="Power", configurable=True,description="Power Setting [0-100]")])
|
|
async def setpower(self,Power = 100 ,**kwargs):
|
|
self.power=int(Power)
|
|
if self.power < 0:
|
|
self.power = 0
|
|
if self.power > 100:
|
|
self.power = 100
|
|
await self.set_power(self.power)
|
|
|
|
def get_GPIO_state(self, state):
|
|
# ON
|
|
if state == 1:
|
|
return 1 if self.inverted == False else 0
|
|
# OFF
|
|
if state == 0:
|
|
return 0 if self.inverted == False else 1
|
|
|
|
async def on_start(self):
|
|
self.power = None
|
|
self.gpio = self.props.GPIO
|
|
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.output(self.gpio, self.get_GPIO_state(0))
|
|
self.state = False
|
|
|
|
async def on(self, power = None):
|
|
if power is not None:
|
|
self.power = power
|
|
else:
|
|
self.power = 100
|
|
# await self.set_power(self.power)
|
|
|
|
logger.info("ACTOR %s ON - GPIO %s " % (self.id, self.gpio))
|
|
GPIO.output(self.gpio, self.get_GPIO_state(1))
|
|
self.state = True
|
|
|
|
async def off(self):
|
|
logger.info("ACTOR %s OFF - GPIO %s " % (self.id, self.gpio))
|
|
GPIO.output(self.gpio, self.get_GPIO_state(0))
|
|
self.state = False
|
|
|
|
def get_state(self):
|
|
return self.state
|
|
|
|
async def run(self):
|
|
while self.running == True:
|
|
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(label="Frequency", configurable=True),
|
|
Property.Select(label="Inverted",options=["Yes","No"],description="Inverts PWM load if set to yes (e.g. 90% = 10%). Default: No")])
|
|
class GPIOPWMActor(CBPiActor):
|
|
|
|
# Custom property which can be configured by the user
|
|
@action("Set Power", parameters=[Property.Number(label="Power", configurable=True,description="Power Setting [0-100]")])
|
|
async def setpower(self,Power = 100 ,**kwargs):
|
|
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 on_start(self):
|
|
self.gpio = self.props.get("GPIO", None)
|
|
self.inverted = self.props.get("Inverted", "No")
|
|
self.frequency = self.props.get("Frequency", 0.5)
|
|
if self.gpio is not None:
|
|
GPIO.setup(self.gpio, GPIO.OUT)
|
|
if self.inverted == "No":
|
|
GPIO.output(self.gpio, 0)
|
|
else:
|
|
GPIO.output(self.gpio, 1)
|
|
self.state = False
|
|
self.power = None
|
|
self.p = None
|
|
pass
|
|
|
|
async def on(self, power = None):
|
|
logging.debug("PWM Actor Power: {}".format(power))
|
|
if power is not None:
|
|
self.power = power
|
|
else:
|
|
self.power = 100
|
|
|
|
logging.debug("PWM Final Power: {}".format(self.power))
|
|
|
|
logger.debug("PWM ACTOR %s ON - GPIO %s - Frequency %s - Power %s" % (self.id, self.gpio,self.frequency,self.power))
|
|
try:
|
|
if self.p is None:
|
|
self.p = GPIO.PWM(int(self.gpio), float(self.frequency))
|
|
if self.inverted == "No":
|
|
self.p.start(self.power)
|
|
else:
|
|
self.p.start(100- self.power)
|
|
self.state = True
|
|
# await self.cbpi.actor.actor_update(self.id,self.power)
|
|
except:
|
|
pass
|
|
|
|
async def off(self):
|
|
logger.info("PWM ACTOR %s OFF - GPIO %s " % (self.id, self.gpio))
|
|
if self.inverted == "No":
|
|
self.p.ChangeDutyCycle(0)
|
|
else:
|
|
self.p.ChangeDutyCycle(100)
|
|
|
|
self.state = False
|
|
|
|
async def set_power(self, power):
|
|
if self.p and self.state == True:
|
|
if self.inverted == "No":
|
|
self.p.ChangeDutyCycle(power)
|
|
else:
|
|
self.p.ChangeDutyCycle(100 - power) # Set power to 100-value to invert output
|
|
await self.cbpi.actor.actor_update(self.id,power)
|
|
pass
|
|
|
|
def get_state(self):
|
|
return self.state
|
|
|
|
async def run(self):
|
|
while self.running == True:
|
|
await asyncio.sleep(1)
|
|
|
|
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("GPIOActor", GPIOActor)
|
|
cbpi.plugin.register("GPIOPWMActor", GPIOPWMActor)
|