initialize
This commit is contained in:
220
LVX6048/powermon-patches/mqttbroker.py
Normal file
220
LVX6048/powermon-patches/mqttbroker.py
Normal file
@@ -0,0 +1,220 @@
|
||||
""" powermon / libs / mqttbroker.py """
|
||||
import logging
|
||||
from time import sleep
|
||||
|
||||
import paho.mqtt.client as mqtt_client
|
||||
|
||||
from powermon.libs.config import safe_config
|
||||
|
||||
# Set-up logger
|
||||
log = logging.getLogger("mqttbroker")
|
||||
|
||||
|
||||
class MqttBroker:
|
||||
""" Wrapper for mqtt broker connectivity and message proccessing """
|
||||
def __str__(self):
|
||||
if self.disabled:
|
||||
return "MqttBroker DISABLED"
|
||||
else:
|
||||
return f"MqttBroker name: {self.name}, port: {self.port}, user: {self.username}"
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, config=None) -> 'MqttBroker':
|
||||
""" build the mqtt broker object from a config dict """
|
||||
log.debug("mqttbroker config: %s", safe_config(config))
|
||||
|
||||
if config:
|
||||
name = config.get("name")
|
||||
port = config.get("port", 1883)
|
||||
username = config.get("username")
|
||||
password = config.get("password")
|
||||
mqtt_broker = cls(name=name, port=port, username=username, password=password)
|
||||
mqtt_broker.adhoc_topic = config.get("adhoc_topic")
|
||||
mqtt_broker.adhoc_result_topic = config.get("adhoc_result_topic")
|
||||
return mqtt_broker
|
||||
else:
|
||||
return cls(name=None)
|
||||
|
||||
def __init__(self, name, port=None, username=None, password=None):
|
||||
self.name = name
|
||||
self.port = port
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.is_connected = False
|
||||
|
||||
if self.name is None:
|
||||
self.disabled = True
|
||||
else:
|
||||
self.disabled = False
|
||||
self.mqttc = mqtt_client.Client()
|
||||
|
||||
@property
|
||||
def adhoc_topic(self) -> str:
|
||||
""" return the adhoc command topic """
|
||||
return getattr(self, "_adhoc_topic", None)
|
||||
|
||||
@adhoc_topic.setter
|
||||
def adhoc_topic(self, value):
|
||||
log.debug("setting adhoc topic to: %s", value)
|
||||
self._adhoc_topic = value
|
||||
|
||||
@property
|
||||
def adhoc_result_topic(self) -> str:
|
||||
""" return the adhoc result topic """
|
||||
return getattr(self, "_adhoc_result_topic", None)
|
||||
|
||||
@adhoc_result_topic.setter
|
||||
def adhoc_result_topic(self, value):
|
||||
log.debug("setting adhoc result topic to: %s", value)
|
||||
self._adhoc_result_topic = value
|
||||
|
||||
def on_connect(self, client, userdata, flags, rc):
|
||||
""" callback for connect """
|
||||
# 0: Connection successful
|
||||
# 1: Connection refused - incorrect protocol version
|
||||
# 2: Connection refused - invalid client identifier
|
||||
# 3: Connection refused - server unavailable
|
||||
# 4: Connection refused - bad username or password
|
||||
# 5: Connection refused - not authorised
|
||||
# 6-255: Currently unused.
|
||||
log.debug("on_connect called - client: %s, userdata: %s, flags: %s", client, userdata, flags)
|
||||
connection_result = [
|
||||
"Connection successful",
|
||||
"Connection refused - incorrect protocol version",
|
||||
"Connection refused - invalid client identifier",
|
||||
"Connection refused - server unavailable",
|
||||
"Connection refused - bad username or password",
|
||||
"Connection refused - not authorised",
|
||||
]
|
||||
log.debug("MqttBroker connection returned result: %s %s", rc, connection_result[rc])
|
||||
if rc == 0:
|
||||
self.is_connected = True
|
||||
return
|
||||
self.is_connected = False
|
||||
|
||||
def on_disconnect(self, client, userdata, rc):
|
||||
""" callback for disconnect """
|
||||
log.debug("on_disconnect called - client: %s, userdata: %s, rc: %s", client, userdata, rc)
|
||||
self.is_connected = False
|
||||
|
||||
def connect(self):
|
||||
""" connect to mqtt broker """
|
||||
if self.disabled:
|
||||
log.info("MQTT broker not enabled, was a broker name defined? '%s'", self.name)
|
||||
return
|
||||
if not self.name:
|
||||
log.info("MQTT could not connect as no broker name")
|
||||
return
|
||||
self.mqttc.on_connect = self.on_connect
|
||||
self.mqttc.on_disconnect = self.on_disconnect
|
||||
# if name is screen just return without connecting
|
||||
if self.name == "screen":
|
||||
# allows checking of message formats
|
||||
return
|
||||
try:
|
||||
log.debug("Connecting to %s on port %s", self.name, self.port)
|
||||
if self.username:
|
||||
# auth = {"username": mqtt_user, "password": mqtt_pass}
|
||||
_password = "********" if self.password is not None else "None"
|
||||
log.info("Using mqtt authentication, username: %s, password: %s", self.username, _password)
|
||||
self.mqttc.username_pw_set(self.username, password=self.password)
|
||||
else:
|
||||
log.debug("No mqtt authentication used")
|
||||
# auth = None
|
||||
self.mqttc.connect(self.name, port=self.port, keepalive=60)
|
||||
self.mqttc.loop_start()
|
||||
sleep(1)
|
||||
except (ConnectionRefusedError, OSError) as ex:
|
||||
log.warning("%s connection failed: '%s'", self.name, ex)
|
||||
|
||||
def start(self):
|
||||
""" start mqtt broker """
|
||||
if self.disabled:
|
||||
return
|
||||
if self.is_connected:
|
||||
self.mqttc.loop_start()
|
||||
|
||||
def stop(self):
|
||||
""" stop mqtt broker """
|
||||
log.debug("Stopping mqttbroker connection")
|
||||
if self.disabled:
|
||||
return
|
||||
self.mqttc.loop_stop()
|
||||
|
||||
# def set(self, variable, value):
|
||||
# setattr(self, variable, value)
|
||||
|
||||
# def update(self, variable, value):
|
||||
# # only override if value is not None
|
||||
# if value is None:
|
||||
# return
|
||||
# setattr(self, variable, value)
|
||||
|
||||
def subscribe(self, topic, callback):
|
||||
""" subscribe to a mqtt topic """
|
||||
if not self.name:
|
||||
return
|
||||
if self.disabled:
|
||||
return
|
||||
# check if connected, connect if not
|
||||
if not self.is_connected:
|
||||
log.debug("Not connected, connecting")
|
||||
self.connect()
|
||||
# Register callback
|
||||
self.mqttc.on_message = callback
|
||||
if self.is_connected:
|
||||
# Subscribe to command topic
|
||||
log.debug("Subscribing to topic: %s", topic)
|
||||
self.mqttc.subscribe(topic, qos=0)
|
||||
else:
|
||||
log.warning("Did not subscribe to topic: %s as not connected to broker", topic)
|
||||
|
||||
def post_adhoc_command(self, command_code):
|
||||
""" shortcut function to publish an adhoc command """
|
||||
self.publish(topic=self.adhoc_topic, payload=command_code)
|
||||
|
||||
def post_adhoc_result(self, payload):
|
||||
""" shortcut function to publish the results of an adhoc command """
|
||||
self.publish(topic=self.adhoc_result_topic, payload=payload)
|
||||
|
||||
|
||||
def publish(self, topic: str = None, payload: str = None):
|
||||
""" function to publish messages to mqtt broker """
|
||||
if self.disabled:
|
||||
log.debug("Cannot publish msg as mqttbroker disabled")
|
||||
return
|
||||
# log.debug("Publishing '%s' to '%s'", payload, topic)
|
||||
if self.name == "screen":
|
||||
print(f"mqtt debug - topic: '{topic}', payload: '{payload}'")
|
||||
return
|
||||
# check if connected, connect if not
|
||||
if not self.is_connected:
|
||||
log.debug("Not connected, connecting")
|
||||
self.connect()
|
||||
sleep(1)
|
||||
if not self.is_connected:
|
||||
log.warning("mqtt broker did not connect")
|
||||
return
|
||||
if isinstance(topic, bytes):
|
||||
topic = topic.decode('utf-8')
|
||||
if isinstance(payload, bytes):
|
||||
payload = payload.decode('utf-8')
|
||||
try:
|
||||
infot = self.mqttc.publish(topic, payload)
|
||||
infot.wait_for_publish(5)
|
||||
except (OSError, RuntimeError, ValueError) as e:
|
||||
log.warning("mqtt publish failed: %s", e)
|
||||
|
||||
# def setAdhocCommands(self, config={}, callback=None):
|
||||
# if not config:
|
||||
# return
|
||||
# if self.disabled:
|
||||
# log.debug("Cannot setAdhocCommands as mqttbroker disabled")
|
||||
# return
|
||||
|
||||
# adhoc_commands = config.get("adhoc_commands")
|
||||
# # sub to command topic if defined
|
||||
# adhoc_commands_topic = adhoc_commands.get("topic")
|
||||
# if adhoc_commands_topic is not None:
|
||||
# log.info("Setting adhoc commands topic to %s", adhoc_commands_topic)
|
||||
# self.subscribe(adhoc_commands_topic, callback)
|
||||
Reference in New Issue
Block a user