diff --git a/cbpi/__init__.py b/cbpi/__init__.py index 7455d4e..c45fc4e 100644 --- a/cbpi/__init__.py +++ b/cbpi/__init__.py @@ -1 +1 @@ -__version__ = "4.0.0.47" +__version__ = "4.0.0.54" diff --git a/cbpi/cli.py b/cbpi/cli.py index 5b0b4fd..7552600 100644 --- a/cbpi/cli.py +++ b/cbpi/cli.py @@ -255,11 +255,15 @@ def plugins_list(): data = yaml.load(f, Loader=yaml.FullLoader) for p in data["plugins"]: - p_metadata= metadata(p) - p_Homepage= p_metadata['Home-page'] - p_version = p_metadata['Version'] - p_Author = p_metadata['Author'] - print("- ({})\t{}".format(p_version,p)) + try: + p_metadata= metadata(p) + p_Homepage= p_metadata['Home-page'] + p_version = p_metadata['Version'] + p_Author = p_metadata['Author'] + print("- ({})\t{}".format(p_version,p)) + except Exception as e: + print (e) + pass except Exception as e: print(e) pass diff --git a/cbpi/controller/actor_controller.py b/cbpi/controller/actor_controller.py index 6ecfcbe..aade888 100644 --- a/cbpi/controller/actor_controller.py +++ b/cbpi/controller/actor_controller.py @@ -11,6 +11,8 @@ class ActorController(BasicController): async def on(self, id, power=None): try: item = self.find_by_id(id) + if item.power: + power = item.power if item.instance.state is False: await item.instance.on(power) await self.push_udpate() diff --git a/cbpi/controller/satellite_controller.py b/cbpi/controller/satellite_controller.py index 6cd47b7..4d29dda 100644 --- a/cbpi/controller/satellite_controller.py +++ b/cbpi/controller/satellite_controller.py @@ -21,7 +21,8 @@ class SatelliteController: self.client = None self.topic_filters = [ ("cbpi/actor/+/on", self._actor_on), - ("cbpi/actor/+/off", self._actor_off) + ("cbpi/actor/+/off", self._actor_off), + ("cbpi/actor/+/power", self._actor_power), ] self.tasks = set() @@ -33,7 +34,7 @@ class SatelliteController: try: await self.client.publish(topic, message, qos=1, retain=retain) except: - self.logger.warning("Faild to push data via mqtt") + self.logger.warning("Failed to push data via mqtt") async def _actor_on(self, messages): async for message in messages: @@ -41,7 +42,7 @@ class SatelliteController: topic_key = message.topic.split("/") await self.cbpi.actor.on(topic_key[2]) except: - self.logger.warning("Faild to process actor on via mqtt") + self.logger.warning("Failed to process actor on via mqtt") async def _actor_off(self, messages): async for message in messages: @@ -49,7 +50,24 @@ class SatelliteController: topic_key = message.topic.split("/") await self.cbpi.actor.off(topic_key[2]) except: - self.logger.warning("Faild to process actor off via mqtt") + self.logger.warning("Failed to process actor off via mqtt") + + async def _actor_power(self, messages): + async for message in messages: + try: + topic_key = message.topic.split("/") + try: + power=int(message.payload.decode()) + if power > 100: + power = 100 + if power < 0: + power = 0 + await self.cbpi.actor.set_power(topic_key[2],power) + await self.cbpi.actor.actor_update(topic_key[2],power) + except: + self.logger.warning("Failed to set actor power via mqtt. No valid power in message") + except: + self.logger.warning("Failed to set actor power via mqtt") def subcribe(self, topic, method): task = asyncio.create_task(self._subcribe(topic, method)) @@ -63,11 +81,9 @@ class SatelliteController: await self.client.subscribe(topic) async for message in messages: await method(message.payload.decode()) - except asyncio.CancelledError as e: + except asyncio.CancelledError: # Cancel - self.logger.warning( - "Sub CancelledError Exception: {}".format(e)) - return + self.logger.warning("Sub Cancelled") except MqttError as e: self.logger.error("Sub MQTT Exception: {}".format(e)) except Exception as e: diff --git a/cbpi/craftbeerpi.py b/cbpi/craftbeerpi.py index 0c92028..e8a6067 100644 --- a/cbpi/craftbeerpi.py +++ b/cbpi/craftbeerpi.py @@ -113,7 +113,7 @@ class CraftBeerPi: self.upload : UploadController = UploadController(self) self.notification : NotificationController = NotificationController(self) self.satellite = None - if self.static_config.get("mqtt", False) is True: + if str(self.static_config.get("mqtt", False)).lower() == "true": self.satellite: SatelliteController = SatelliteController(self) self.dashboard = DashboardController(self) diff --git a/cbpi/extension/mashstep/__init__.py b/cbpi/extension/mashstep/__init__.py index 2fe8dfd..ee7c924 100644 --- a/cbpi/extension/mashstep/__init__.py +++ b/cbpi/extension/mashstep/__init__.py @@ -15,7 +15,6 @@ from typing import KeysView from cbpi.api.config import ConfigType from cbpi.api.base import CBPiBase import numpy as np -#import scipy.optimize import warnings diff --git a/cbpi/extension/mqtt_actor/__init__.py b/cbpi/extension/mqtt_actor/__init__.py new file mode 100644 index 0000000..b7e8cf1 --- /dev/null +++ b/cbpi/extension/mqtt_actor/__init__.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +import asyncio +import json +from cbpi.api import parameters, Property, CBPiActor +from cbpi.api import * + +@parameters([Property.Text(label="Topic", configurable=True, description = "MQTT Topic")]) +class MQTTActor(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=round(Power) + if self.power < 0: + self.power = 0 + if self.power > 100: + self.power = 100 + await self.set_power(self.power) + + def __init__(self, cbpi, id, props): + super(MQTTActor, self).__init__(cbpi, id, props) + + async def on_start(self): + self.topic = self.props.get("Topic", None) + self.power = 100 + + async def on(self, power=None): + if power is not None: + if power != self.power: + power = min(100, power) + power = max(0, power) + self.power = round(power) + await self.cbpi.satellite.publish(self.topic, json.dumps( + {"state": "on", "power": self.power}), True) + self.state = True + pass + + async def off(self): + self.state = False + await self.cbpi.satellite.publish(self.topic, json.dumps( + {"state": "off", "power": self.power}), True) + pass + + async def run(self): + while self.running: + await asyncio.sleep(1) + + def get_state(self): + return self.state + + async def set_power(self, power): + self.power = round(power) + if self.state == True: + await self.on(power) + else: + await self.off() + await self.cbpi.actor.actor_update(self.id,power) + pass + +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: + ''' + if str(cbpi.static_config.get("mqtt", False)).lower() == "true": + cbpi.plugin.register("MQTTActor", MQTTActor) diff --git a/cbpi/extension/mqtt_actor/config.yaml b/cbpi/extension/mqtt_actor/config.yaml new file mode 100644 index 0000000..f4aeff5 --- /dev/null +++ b/cbpi/extension/mqtt_actor/config.yaml @@ -0,0 +1,3 @@ +name: MQTTActor +version: 4 +active: true diff --git a/cbpi/extension/mqtt_sensor/__init__.py b/cbpi/extension/mqtt_sensor/__init__.py index 481beb0..4564416 100644 --- a/cbpi/extension/mqtt_sensor/__init__.py +++ b/cbpi/extension/mqtt_sensor/__init__.py @@ -2,24 +2,38 @@ import asyncio from cbpi.api import parameters, Property, CBPiSensor +from cbpi.api import * +import logging +import json - -@parameters([Property.Text(label="Topic", configurable=True)]) +@parameters([Property.Text(label="Topic", configurable=True, description="MQTT Topic"), + Property.Text(label="PayloadDictionary", configurable=True, default_value="", + description="Where to find msg in payload, leave blank for raw payload")]) class MQTTSensor(CBPiSensor): - async def on_message(self, message): - try: - self.value = float(message) - self.log_data(self.value) - self.push_update(self.value) - except Exception as e: - print(e) - def __init__(self, cbpi, id, props): super(MQTTSensor, self).__init__(cbpi, id, props) - self.mqtt_task = self.cbpi.satellite.subcribe(self.props.Topic, self.on_message) + self.Topic = self.props.get("Topic", None) + self.payload_text = self.props.get("PayloadDictionary", None) + if self.payload_text != None: + self.payload_text = self.payload_text.split('.') + self.mqtt_task = self.cbpi.satellite.subcribe(self.Topic, self.on_message) self.value: int = 0 + async def on_message(self, message): + val = json.loads(message) + try: + if self.payload_text is not None: + for key in self.payload_text: + val = val.get(key, None) + + if isinstance(val, (int, float, str)): + self.value = float(val) + self.log_data(self.value) + self.push_update(self.value) + except Exception as e: + logging.info("MQTT Sensor Error {}".format(e)) + async def run(self): while self.running: await asyncio.sleep(1) @@ -44,5 +58,5 @@ def setup(cbpi): :param cbpi: the cbpi core :return: ''' - if cbpi.static_config.get("mqtt", False) is True: + if str(cbpi.static_config.get("mqtt", False)).lower() == "true": cbpi.plugin.register("MQTTSensor", MQTTSensor) diff --git a/setup.py b/setup.py index 6dc39e9..d293b75 100644 --- a/setup.py +++ b/setup.py @@ -37,10 +37,9 @@ setup(name='cbpi', 'asyncio-mqtt', 'psutil==5.8.0', 'numpy==1.20.3', - 'scipy', 'cbpi4ui', 'importlib_metadata'] + ( - ['RPi.GPIO'] if platform.uname()[1] == "raspberrypi" else [] ), + ['RPi.GPIO==0.7.1a4'] if platform.uname()[1] == "raspberrypi" else [] ), dependency_links=[ 'https://testpypi.python.org/pypi',