diff --git a/cbpi/controller/satellite_controller.py b/cbpi/controller/satellite_controller.py index 4d29dda..e12223c 100644 --- a/cbpi/controller/satellite_controller.py +++ b/cbpi/controller/satellite_controller.py @@ -33,24 +33,24 @@ class SatelliteController: if self.client is not None and self.client._connected: try: await self.client.publish(topic, message, qos=1, retain=retain) - except: - self.logger.warning("Failed to push data via mqtt") + except Exception as e: + self.logger.warning("Failed to push data via mqtt: {}".format(e)) async def _actor_on(self, messages): async for message in messages: try: topic_key = message.topic.split("/") await self.cbpi.actor.on(topic_key[2]) - except: - self.logger.warning("Failed to process actor on via mqtt") + except Exception as e: + self.logger.warning("Failed to process actor on via mqtt: {}".format(e)) async def _actor_off(self, messages): async for message in messages: try: topic_key = message.topic.split("/") await self.cbpi.actor.off(topic_key[2]) - except: - self.logger.warning("Failed to process actor off via mqtt") + except Exception as e: + self.logger.warning("Failed to process actor off via mqtt: {}".format(e)) async def _actor_power(self, messages): async for message in messages: diff --git a/cbpi/extension/mqtt_actor/__init__.py b/cbpi/extension/mqtt_actor/__init__.py index b7e8cf1..bab41c6 100644 --- a/cbpi/extension/mqtt_actor/__init__.py +++ b/cbpi/extension/mqtt_actor/__init__.py @@ -1,61 +1,8 @@ # -*- 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 +from .mqtt_actor import MQTTActor +from .generic_mqtt_actor import GenericMqttActor +from .tasmota_mqtt_actor import TasmotaMqttActor def setup(cbpi): ''' @@ -67,3 +14,5 @@ def setup(cbpi): ''' if str(cbpi.static_config.get("mqtt", False)).lower() == "true": cbpi.plugin.register("MQTTActor", MQTTActor) + cbpi.plugin.register("MQTT Actor (Generic)", GenericMqttActor) + cbpi.plugin.register("MQTT Actor (Tasmota)", TasmotaMqttActor) \ No newline at end of file diff --git a/cbpi/extension/mqtt_actor/generic_mqtt_actor.py b/cbpi/extension/mqtt_actor/generic_mqtt_actor.py new file mode 100644 index 0000000..c1a5b17 --- /dev/null +++ b/cbpi/extension/mqtt_actor/generic_mqtt_actor.py @@ -0,0 +1,37 @@ +from cbpi.api import parameters, Property +from . import MQTTActor + +@parameters([ + Property.Text(label="Topic", configurable=True, description = "MQTT Topic"), + Property.Text(label="Payload", configurable=True, description = "Payload that is sent as MQTT message. Available placeholders are {switch_onoff}: [on|off], {switch_10}: [1|0], {power}: [0-100].") +]) +class GenericMqttActor(MQTTActor): + def __init__(self, cbpi, id, props): + MQTTActor.__init__(self, cbpi, id, props) + self.payload = "" + + async def on_start(self): + await MQTTActor.on_start(self) + self.payload = self.props.get("Payload", "{{\"state\": \"{switch_onoff}\", \"power\": {power}}}") + + def normalize_power_value(self, power): + if power is not None: + if power != self.power: + power = min(100, power) + power = max(0, power) + self.power = round(power) + + async def publish_mqtt_message(self, topic, payload): + self.logger.info("Publish '{payload}' to '{topic}'".format(payload = payload, topic = self.topic)) + await self.cbpi.satellite.publish(self.topic, payload, True) + + async def on(self, power=None): + self.normalize_power_value(power) + formatted_payload = self.payload.format(switch_onoff = "on", switch_10 = 1, power = self.power) + await self.publish_mqtt_message(self.topic, formatted_payload) + self.state = True + + async def off(self): + formatted_payload = self.payload.format(switch_onoff = "off", switch_10 = 0, power = self.power) + await self.publish_mqtt_message(self.topic, formatted_payload) + self.state = False \ No newline at end of file diff --git a/cbpi/extension/mqtt_actor/mqtt_actor.py b/cbpi/extension/mqtt_actor/mqtt_actor.py new file mode 100644 index 0000000..e9a6f4a --- /dev/null +++ b/cbpi/extension/mqtt_actor/mqtt_actor.py @@ -0,0 +1,57 @@ +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 \ No newline at end of file diff --git a/cbpi/extension/mqtt_actor/tasmota_mqtt_actor.py b/cbpi/extension/mqtt_actor/tasmota_mqtt_actor.py new file mode 100644 index 0000000..5b0e44b --- /dev/null +++ b/cbpi/extension/mqtt_actor/tasmota_mqtt_actor.py @@ -0,0 +1,13 @@ +from cbpi.api import parameters, Property +from . import GenericMqttActor + +@parameters([ + Property.Text(label="Topic", configurable=True, description = "MQTT Topic"), +]) +class TasmotaMqttActor(GenericMqttActor): + def __init__(self, cbpi, id, props): + GenericMqttActor.__init__(self, cbpi, id, props) + + async def on_start(self): + await GenericMqttActor.on_start(self) + self.payload = "{switch_onoff}" \ No newline at end of file