Merge pull request #133 from PiBrewing/development

Merge from Development
This commit is contained in:
Alexander Vollkopf 2024-04-15 07:13:23 +02:00 committed by GitHub
commit 92f1433530
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 57 additions and 71 deletions

View file

@ -1,3 +1,3 @@
__version__ = "4.3.2" __version__ = "4.4.0"
__codename__ = "Winter Storm" __codename__ = "Yeast Starter"

View file

@ -53,7 +53,7 @@ class SatelliteController:
except asyncio.CancelledError: except asyncio.CancelledError:
pass pass
self.client = Client(self.host, port=self.port, username=self.username, password=self.password, will=Will(topic="cbpi/disconnect", payload="CBPi Server Disconnected"),client_id=self.client_id) self.client = Client(self.host, port=self.port, username=self.username, password=self.password, will=Will(topic="cbpi/disconnect", payload="CBPi Server Disconnected"),identifier=self.client_id)
self.loop = asyncio.get_event_loop() self.loop = asyncio.get_event_loop()
## Listen for mqtt messages in an (unawaited) asyncio task ## Listen for mqtt messages in an (unawaited) asyncio task
task = self.loop.create_task(self.listen()) task = self.loop.create_task(self.listen())
@ -67,9 +67,8 @@ class SatelliteController:
while True: while True:
try: try:
async with self.client as client: async with self.client as client:
async with client.messages() as messages:
await client.subscribe("#") await client.subscribe("#")
async for message in messages: async for message in client.messages:
for topic_filter in self.topic_filters: for topic_filter in self.topic_filters:
topic = topic_filter[0] topic = topic_filter[0]
method = topic_filter[1] method = topic_filter[1]
@ -158,30 +157,10 @@ class SatelliteController:
except Exception as e: except Exception as e:
self.logger.warning("Failed to send sensorupdate via mqtt: {}".format(e)) self.logger.warning("Failed to send sensorupdate via mqtt: {}".format(e))
def subcribe(self, topic, method): def subscribe(self, topic, method):
task = asyncio.create_task(self._subcribe(topic, method)) self.topic_filters.append((topic,method))
return task return True
async def _subcribe(self, topic, method): def unsubscribe(self, topic, method):
self.error=False self.topic_filters.remove((topic,method))
while True: return True
try:
if self.client._connected.done():
async with self.client.messages() as messages:
await self.client.subscribe(topic)
async for message in messages:
if message.topic.matches(topic):
await method(message.payload.decode())
except asyncio.CancelledError:
# Cancel
self.logger.warning("Subscription {} Cancelled".format(topic))
self.error=True
except MqttError as e:
self.logger.error("Sub MQTT Exception: {}".format(e))
except Exception as e:
self.logger.error("Sub Exception: {}".format(e))
# wait before try to resubscribe
if self.error == True:
break
else:
await asyncio.sleep(5)

View file

@ -263,7 +263,7 @@ class CraftBeerPi:
f = Figlet(font='big') f = Figlet(font='big')
logger.warning("\n%s" % f.renderText("CraftBeerPi %s " % self.version)) logger.warning("\n%s" % f.renderText("CraftBeerPi %s " % self.version))
logger.warning("www.CraftBeerPi.com") logger.warning("www.CraftBeerPi.com")
logger.warning("(c) 2021/2022/2023 Manuel Fritsch / Alexander Vollkopf") logger.warning("(c) 2021 - 2024 Manuel Fritsch / Alexander Vollkopf")
def _setup_http_index(self): def _setup_http_index(self):
async def http_index(request): async def http_index(request):

View file

@ -97,7 +97,9 @@ class GPIOActor(CBPiActor):
pass 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)]) @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): class GPIOPWMActor(CBPiActor):
# Custom property which can be configured by the user # Custom property which can be configured by the user
@ -113,10 +115,14 @@ class GPIOPWMActor(CBPiActor):
async def on_start(self): async def on_start(self):
self.gpio = self.props.get("GPIO", None) self.gpio = self.props.get("GPIO", None)
self.inverted = self.props.get("Inverted", "No")
self.frequency = self.props.get("Frequency", 0.5) self.frequency = self.props.get("Frequency", 0.5)
if self.gpio is not None: if self.gpio is not None:
GPIO.setup(self.gpio, GPIO.OUT) GPIO.setup(self.gpio, GPIO.OUT)
if self.inverted == "No":
GPIO.output(self.gpio, 0) GPIO.output(self.gpio, 0)
else:
GPIO.output(self.gpio, 1)
self.state = False self.state = False
self.power = None self.power = None
self.p = None self.p = None
@ -135,7 +141,10 @@ class GPIOPWMActor(CBPiActor):
try: try:
if self.p is None: if self.p is None:
self.p = GPIO.PWM(int(self.gpio), float(self.frequency)) self.p = GPIO.PWM(int(self.gpio), float(self.frequency))
if self.inverted == "No":
self.p.start(self.power) self.p.start(self.power)
else:
self.p.start(100- self.power)
self.state = True self.state = True
# await self.cbpi.actor.actor_update(self.id,self.power) # await self.cbpi.actor.actor_update(self.id,self.power)
except: except:
@ -143,12 +152,19 @@ class GPIOPWMActor(CBPiActor):
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))
if self.inverted == "No":
self.p.ChangeDutyCycle(0) self.p.ChangeDutyCycle(0)
else:
self.p.ChangeDutyCycle(100)
self.state = False self.state = False
async def set_power(self, power): async def set_power(self, power):
if self.p and self.state == True: if self.p and self.state == True:
if self.inverted == "No":
self.p.ChangeDutyCycle(power) 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) await self.cbpi.actor.actor_update(self.id,power)
pass pass

View file

@ -24,7 +24,7 @@ class MQTTSensor(CBPiSensor):
self.payload_text = self.props.get("PayloadDictionary", None) self.payload_text = self.props.get("PayloadDictionary", None)
if self.payload_text != None: if self.payload_text != None:
self.payload_text = self.payload_text.split('.') self.payload_text = self.payload_text.split('.')
self.mqtt_task = self.cbpi.satellite.subcribe(self.Topic, self.on_message) self.subscribed = self.cbpi.satellite.subscribe(self.Topic, self.on_message)
self.value: float = 999 self.value: float = 999
self.timeout=int(self.props.get("Timeout", 60)) self.timeout=int(self.props.get("Timeout", 60))
self.starttime = time.time() self.starttime = time.time()
@ -55,7 +55,7 @@ class MQTTSensor(CBPiSensor):
pass pass
async def on_message(self, message): async def on_message(self, message):
val = json.loads(message) val = json.loads(message.payload.decode())
try: try:
if self.payload_text is not None: if self.payload_text is not None:
for key in self.payload_text: for key in self.payload_text:
@ -130,17 +130,8 @@ class MQTTSensor(CBPiSensor):
return dict(value=self.value) return dict(value=self.value)
async def on_stop(self): async def on_stop(self):
was_cancelled=False self.subscribed = self.cbpi.satellite.unsubscribe(self.Topic, self.on_message)
if not self.mqtt_task.done():
logging.info("Task not done -> cancelling")
was_cancelled = self.mqtt_task.cancel()
try:
logging.info("Trying to call cancelled task")
await self.mqtt_task
except asyncio.CancelledError:
logging.info("Task has been Cancelled")
pass
logging.info("Task cancelled: {}".format(was_cancelled))
def setup(cbpi): def setup(cbpi):
''' '''

View file

@ -1,5 +1,5 @@
typing-extensions>=4 typing-extensions>=4
aiohttp==3.9.3 aiohttp==3.9.4
aiohttp-auth==0.1.1 aiohttp-auth==0.1.1
aiohttp-route-decorator==0.1.4 aiohttp-route-decorator==0.1.4
aiohttp-security==0.5.0 aiohttp-security==0.5.0
@ -8,22 +8,22 @@ aiohttp-swagger==1.0.16
async-timeout==4.0.3 async-timeout==4.0.3
aiojobs==1.2.1 aiojobs==1.2.1
aiosqlite==0.17.0 aiosqlite==0.17.0
cryptography==41.0.7 cryptography==42.0.5
pyopenssl==23.3.0 pyopenssl==24.1.0
requests==2.31.0 requests==2.31.0
voluptuous==0.13.1 voluptuous==0.14.2
pyfiglet==1.0.2 pyfiglet==1.0.2
pandas==1.5.3 pandas==2.2.2
shortuuid==1.0.11 shortuuid==1.0.13
tabulate==0.9.0 tabulate==0.9.0
numpy==1.24.1 numpy==1.26.4
cbpi4gui cbpi4gui
click==8.1.7 click==8.1.7
importlib_metadata==4.11.1 importlib_metadata==4.11.1
aiomqtt==1.2.1 aiomqtt==2.0.1
psutil==5.9.6 psutil==5.9.8
zipp>=0.5 zipp>=0.5
colorama==0.4.6 colorama==0.4.6
pytest-aiohttp pytest-aiohttp
coverage==6.3.1 coverage==6.3.1
inquirer==3.1.3 inquirer==3.2.4

View file

@ -39,7 +39,7 @@ setup(name='cbpi4',
long_description_content_type='text/markdown', long_description_content_type='text/markdown',
install_requires=[ install_requires=[
"typing-extensions>=4", "typing-extensions>=4",
"aiohttp==3.9.3", "aiohttp==3.9.4",
"aiohttp-auth==0.1.1", "aiohttp-auth==0.1.1",
"aiohttp-route-decorator==0.1.4", "aiohttp-route-decorator==0.1.4",
"aiohttp-security==0.5.0", "aiohttp-security==0.5.0",
@ -48,22 +48,22 @@ setup(name='cbpi4',
"async-timeout==4.0.3", "async-timeout==4.0.3",
"aiojobs==1.2.1 ", "aiojobs==1.2.1 ",
"aiosqlite==0.17.0", "aiosqlite==0.17.0",
"cryptography==41.0.7", "cryptography==42.0.5",
"pyopenssl==23.3.0", "pyopenssl==24.1.0",
"requests==2.31.0", "requests==2.31.0",
"voluptuous==0.13.1", "voluptuous==0.14.2",
"pyfiglet==1.0.2", "pyfiglet==1.0.2",
'click==8.1.7', 'click==8.1.7',
'shortuuid==1.0.11', 'shortuuid==1.0.13',
'tabulate==0.9.0', 'tabulate==0.9.0',
'aiomqtt==1.2.1', 'aiomqtt==2.0.1',
'inquirer==3.1.3', 'inquirer==3.2.4',
'colorama==0.4.6', 'colorama==0.4.6',
'psutil==5.9.6', 'psutil==5.9.8',
'cbpi4gui', 'cbpi4gui',
'importlib_metadata', 'importlib_metadata',
'numpy==1.24.1', 'numpy==1.26.4',
'pandas==1.5.3'] + ( 'pandas==2.2.2'] + (
['rpi-lgpio'] if raspberrypi else [] ), ['rpi-lgpio'] if raspberrypi else [] ),
dependency_links=[ dependency_links=[