From 479148f7719ba4c6069bb3d3b3eab56602770025 Mon Sep 17 00:00:00 2001 From: avollkopf <43980694+avollkopf@users.noreply.github.com> Date: Sat, 2 Dec 2023 11:29:28 +0100 Subject: [PATCH 1/7] GPIOZero Actor test for Pi5 --- cbpi/__init__.py | 4 +- cbpi/extension/gpiozeroactor/__init__.py | 196 +++++++++++++++++++++++ cbpi/extension/gpiozeroactor/config.yaml | 3 + setup.py | 2 +- 4 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 cbpi/extension/gpiozeroactor/__init__.py create mode 100644 cbpi/extension/gpiozeroactor/config.yaml diff --git a/cbpi/__init__.py b/cbpi/__init__.py index 130d75c..e280147 100644 --- a/cbpi/__init__.py +++ b/cbpi/__init__.py @@ -1,3 +1,3 @@ -__version__ = "4.2.0" -__codename__ = "Indian Summer" +__version__ = "4.3.0.a1" +__codename__ = "Winter Storm" diff --git a/cbpi/extension/gpiozeroactor/__init__.py b/cbpi/extension/gpiozeroactor/__init__.py new file mode 100644 index 0000000..44b0b5b --- /dev/null +++ b/cbpi/extension/gpiozeroactor/__init__.py @@ -0,0 +1,196 @@ +import asyncio +import logging +from unittest.mock import MagicMock, patch + +from cbpi.api import * + + +logger = logging.getLogger(__name__) + +try: + import gpiozero as GPIO +except Exception: + logger.warning("Failed to load gpiozero. Using Mock instead") + MockRPi = MagicMock() + modules = { + "gpiozero": MockRPi.gpiozero + } + patcher = patch.dict("sys.modules", modules) + patcher.start() + import gpiozero + + +@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 GPIOZEROActor(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.led=gpiozero.LED(self.gpio) + if self.inverted: + self.led.on() + else: + self.led.off() + + 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)) + if self.inverted: + self.led.off() + else: + self.led.on() + 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)) + if self.inverted: + self.led.on() + else: + self.led.off() + 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)) + if self.inverted: + self.led.off() + else: + self.led.on() + 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)) + if self.inverted: + self.led.on() + else: + self.led.off() + 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)]) +class GPIOZEROPWMActor(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.frequency = self.props.get("Frequency", 0.5) + if self.gpio is not None: + #GPIO.setup(self.gpio, GPIO.OUT) + #GPIO.output(self.gpio, 0) + self.led=gpiozero.PWMLED(pin=self.gpio,frequency=float(self.frequency)) + self.led.value=0 + 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)) + #self.p.start(self.power) + self.led.value=float(self.power/100) + 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)) + #self.p.ChangeDutyCycle(0) + self.led.value=0 + self.state = False + + async def set_power(self, power): + #if self.p and self.state == True: + # self.p.ChangeDutyCycle(power) + self.led.value=float(self.power/100) + 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("GPIOZEROActor", GPIOZEROActor) + cbpi.plugin.register("GPIOZEROPWMActor", GPIOZEROPWMActor) diff --git a/cbpi/extension/gpiozeroactor/config.yaml b/cbpi/extension/gpiozeroactor/config.yaml new file mode 100644 index 0000000..6128a0e --- /dev/null +++ b/cbpi/extension/gpiozeroactor/config.yaml @@ -0,0 +1,3 @@ +name: GPIOZeroActor +version: 4 +active: true \ No newline at end of file diff --git a/setup.py b/setup.py index 06eafca..f958192 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ setup(name='cbpi4', 'importlib_metadata', 'numpy==1.24.1', 'pandas==1.5.3'] + ( - ['RPi.GPIO==0.7.1'] if raspberrypi else [] ), + ['RPi.GPIO==0.7.1','gpiozero==2.0'] if raspberrypi else [] ), dependency_links=[ 'https://testpypi.python.org/pypi', From 06c3e0a39a3eb2c4d33d7f88462c0a048ab47902 Mon Sep 17 00:00:00 2001 From: avollkopf <43980694+avollkopf@users.noreply.github.com> Date: Sat, 2 Dec 2023 11:30:08 +0100 Subject: [PATCH 2/7] update requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 93dd3b0..f86619c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,3 +26,4 @@ colorama==0.4.6 pytest-aiohttp coverage==6.3.1 inquirer==3.1.3 +gpiozero==2.0 From ef72e9236c58c11c359af3ccf560c707b886fc9b Mon Sep 17 00:00:00 2001 From: avollkopf <43980694+avollkopf@users.noreply.github.com> Date: Sat, 2 Dec 2023 12:54:51 +0100 Subject: [PATCH 3/7] usage of rpi-lgpio package --- cbpi/extension/gpiozeroactor/__init__.py | 196 ----------------------- cbpi/extension/gpiozeroactor/config.yaml | 3 - requirements.txt | 1 - setup.py | 2 +- 4 files changed, 1 insertion(+), 201 deletions(-) delete mode 100644 cbpi/extension/gpiozeroactor/__init__.py delete mode 100644 cbpi/extension/gpiozeroactor/config.yaml diff --git a/cbpi/extension/gpiozeroactor/__init__.py b/cbpi/extension/gpiozeroactor/__init__.py deleted file mode 100644 index 44b0b5b..0000000 --- a/cbpi/extension/gpiozeroactor/__init__.py +++ /dev/null @@ -1,196 +0,0 @@ -import asyncio -import logging -from unittest.mock import MagicMock, patch - -from cbpi.api import * - - -logger = logging.getLogger(__name__) - -try: - import gpiozero as GPIO -except Exception: - logger.warning("Failed to load gpiozero. Using Mock instead") - MockRPi = MagicMock() - modules = { - "gpiozero": MockRPi.gpiozero - } - patcher = patch.dict("sys.modules", modules) - patcher.start() - import gpiozero - - -@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 GPIOZEROActor(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.led=gpiozero.LED(self.gpio) - if self.inverted: - self.led.on() - else: - self.led.off() - - 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)) - if self.inverted: - self.led.off() - else: - self.led.on() - 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)) - if self.inverted: - self.led.on() - else: - self.led.off() - 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)) - if self.inverted: - self.led.off() - else: - self.led.on() - 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)) - if self.inverted: - self.led.on() - else: - self.led.off() - 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)]) -class GPIOZEROPWMActor(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.frequency = self.props.get("Frequency", 0.5) - if self.gpio is not None: - #GPIO.setup(self.gpio, GPIO.OUT) - #GPIO.output(self.gpio, 0) - self.led=gpiozero.PWMLED(pin=self.gpio,frequency=float(self.frequency)) - self.led.value=0 - 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)) - #self.p.start(self.power) - self.led.value=float(self.power/100) - 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)) - #self.p.ChangeDutyCycle(0) - self.led.value=0 - self.state = False - - async def set_power(self, power): - #if self.p and self.state == True: - # self.p.ChangeDutyCycle(power) - self.led.value=float(self.power/100) - 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("GPIOZEROActor", GPIOZEROActor) - cbpi.plugin.register("GPIOZEROPWMActor", GPIOZEROPWMActor) diff --git a/cbpi/extension/gpiozeroactor/config.yaml b/cbpi/extension/gpiozeroactor/config.yaml deleted file mode 100644 index 6128a0e..0000000 --- a/cbpi/extension/gpiozeroactor/config.yaml +++ /dev/null @@ -1,3 +0,0 @@ -name: GPIOZeroActor -version: 4 -active: true \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index f86619c..93dd3b0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,4 +26,3 @@ colorama==0.4.6 pytest-aiohttp coverage==6.3.1 inquirer==3.1.3 -gpiozero==2.0 diff --git a/setup.py b/setup.py index f958192..747e430 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ setup(name='cbpi4', 'importlib_metadata', 'numpy==1.24.1', 'pandas==1.5.3'] + ( - ['RPi.GPIO==0.7.1','gpiozero==2.0'] if raspberrypi else [] ), + ['rpi-lgpio'] if raspberrypi else [] ), dependency_links=[ 'https://testpypi.python.org/pypi', From 22eba69cbc8176cb03b0b7f6c4fcaeb856ddc8ea Mon Sep 17 00:00:00 2001 From: avollkopf <43980694+avollkopf@users.noreply.github.com> Date: Mon, 18 Dec 2023 21:36:56 +0100 Subject: [PATCH 4/7] update requirements --- cbpi/__init__.py | 2 +- requirements.txt | 8 ++++---- setup.py | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cbpi/__init__.py b/cbpi/__init__.py index e280147..d823096 100644 --- a/cbpi/__init__.py +++ b/cbpi/__init__.py @@ -1,3 +1,3 @@ -__version__ = "4.3.0.a1" +__version__ = "4.3.0.a3" __codename__ = "Winter Storm" diff --git a/requirements.txt b/requirements.txt index 93dd3b0..485cb53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,13 @@ typing-extensions>=4 -aiohttp==3.8.6 +aiohttp==3.9.1 aiohttp-auth==0.1.1 aiohttp-route-decorator==0.1.4 -aiohttp-security==0.4.0 +aiohttp-security==0.5.0 aiohttp-session==2.12.0 aiohttp-swagger==1.0.16 -aiojobs==1.1.0 +aiojobs==1.2.1 aiosqlite==0.17.0 -cryptography==41.0.5 +cryptography==41.0.7 pyopenssl==23.3.0 requests==2.31.0 voluptuous==0.13.1 diff --git a/setup.py b/setup.py index 747e430..5389ce4 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ from os import popen, path localsystem = platform.system() raspberrypi=False if localsystem == "Linux": - command="cat /proc/cpuinfo | grep Raspberry" + command="cat /proc/cpuinfo | grep 'Raspberry'" model=popen(command).read() if len(model) != 0: raspberrypi=True @@ -39,15 +39,15 @@ setup(name='cbpi4', long_description_content_type='text/markdown', install_requires=[ "typing-extensions>=4", - "aiohttp==3.8.6", + "aiohttp==3.9.1", "aiohttp-auth==0.1.1", "aiohttp-route-decorator==0.1.4", - "aiohttp-security==0.4.0", + "aiohttp-security==0.5.0", "aiohttp-session==2.12.0", "aiohttp-swagger==1.0.16", - "aiojobs==1.1.0 ", + "aiojobs==1.2.1 ", "aiosqlite==0.17.0", - "cryptography==41.0.5", + "cryptography==41.0.7", "pyopenssl==23.3.0", "requests==2.31.0", "voluptuous==0.13.1", From 99f1175bb8a0c32740b1f7c9af9ee31439a3bfb6 Mon Sep 17 00:00:00 2001 From: avollkopf <43980694+avollkopf@users.noreply.github.com> Date: Mon, 18 Dec 2023 21:56:46 +0100 Subject: [PATCH 5/7] reverting back packages (issues on pi) --- cbpi/__init__.py | 2 +- requirements.txt | 6 +++--- setup.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cbpi/__init__.py b/cbpi/__init__.py index d823096..cb70d5d 100644 --- a/cbpi/__init__.py +++ b/cbpi/__init__.py @@ -1,3 +1,3 @@ -__version__ = "4.3.0.a3" +__version__ = "4.3.0.a4" __codename__ = "Winter Storm" diff --git a/requirements.txt b/requirements.txt index 485cb53..5525103 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,11 @@ typing-extensions>=4 -aiohttp==3.9.1 +aiohttp==3.8.6 aiohttp-auth==0.1.1 aiohttp-route-decorator==0.1.4 -aiohttp-security==0.5.0 +aiohttp-security==0.4.0 aiohttp-session==2.12.0 aiohttp-swagger==1.0.16 -aiojobs==1.2.1 +aiojobs==1.1.0 aiosqlite==0.17.0 cryptography==41.0.7 pyopenssl==23.3.0 diff --git a/setup.py b/setup.py index 5389ce4..f6cc67e 100644 --- a/setup.py +++ b/setup.py @@ -39,13 +39,13 @@ setup(name='cbpi4', long_description_content_type='text/markdown', install_requires=[ "typing-extensions>=4", - "aiohttp==3.9.1", + "aiohttp==3.8.6", "aiohttp-auth==0.1.1", "aiohttp-route-decorator==0.1.4", - "aiohttp-security==0.5.0", + "aiohttp-security==0.4.0", "aiohttp-session==2.12.0", "aiohttp-swagger==1.0.16", - "aiojobs==1.2.1 ", + "aiojobs==1.1.0 ", "aiosqlite==0.17.0", "cryptography==41.0.7", "pyopenssl==23.3.0", From 5bd187eaf5ed669cd36ea6154c9601f3a35f7891 Mon Sep 17 00:00:00 2001 From: avollkopf <43980694+avollkopf@users.noreply.github.com> Date: Sat, 30 Dec 2023 17:10:10 +0100 Subject: [PATCH 6/7] updated requirements --- cbpi/__init__.py | 2 +- requirements.txt | 6 +++--- setup.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cbpi/__init__.py b/cbpi/__init__.py index cb70d5d..5597bb6 100644 --- a/cbpi/__init__.py +++ b/cbpi/__init__.py @@ -1,3 +1,3 @@ -__version__ = "4.3.0.a4" +__version__ = "4.3.0.a5" __codename__ = "Winter Storm" diff --git a/requirements.txt b/requirements.txt index 5525103..485cb53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,11 @@ typing-extensions>=4 -aiohttp==3.8.6 +aiohttp==3.9.1 aiohttp-auth==0.1.1 aiohttp-route-decorator==0.1.4 -aiohttp-security==0.4.0 +aiohttp-security==0.5.0 aiohttp-session==2.12.0 aiohttp-swagger==1.0.16 -aiojobs==1.1.0 +aiojobs==1.2.1 aiosqlite==0.17.0 cryptography==41.0.7 pyopenssl==23.3.0 diff --git a/setup.py b/setup.py index f6cc67e..5389ce4 100644 --- a/setup.py +++ b/setup.py @@ -39,13 +39,13 @@ setup(name='cbpi4', long_description_content_type='text/markdown', install_requires=[ "typing-extensions>=4", - "aiohttp==3.8.6", + "aiohttp==3.9.1", "aiohttp-auth==0.1.1", "aiohttp-route-decorator==0.1.4", - "aiohttp-security==0.4.0", + "aiohttp-security==0.5.0", "aiohttp-session==2.12.0", "aiohttp-swagger==1.0.16", - "aiojobs==1.1.0 ", + "aiojobs==1.2.1 ", "aiosqlite==0.17.0", "cryptography==41.0.7", "pyopenssl==23.3.0", From 272cb9fb19c2f0f650622a40954c0ae458dd0a03 Mon Sep 17 00:00:00 2001 From: avollkopf <43980694+avollkopf@users.noreply.github.com> Date: Sun, 31 Dec 2023 11:45:11 +0100 Subject: [PATCH 7/7] bump release version --- cbpi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cbpi/__init__.py b/cbpi/__init__.py index 5597bb6..f2909db 100644 --- a/cbpi/__init__.py +++ b/cbpi/__init__.py @@ -1,3 +1,3 @@ -__version__ = "4.3.0.a5" +__version__ = "4.3.0" __codename__ = "Winter Storm"