--- a/MqttMonitor/MqttMonitorWidget.py Sun Aug 26 19:40:15 2018 +0200 +++ b/MqttMonitor/MqttMonitorWidget.py Mon Aug 27 19:26:27 2018 +0200 @@ -1,34 +1,213 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# + """ -Module implementing MqttMonitorWidget. +Module implementing the MQTT Monitor widget. """ from __future__ import unicode_literals import os -from PyQt5.QtCore import pyqtSlot +from PyQt5.QtCore import pyqtSlot, QTimer from PyQt5.QtWidgets import QWidget from .Ui_MqttMonitorWidget import Ui_MqttMonitorWidget +from .MqttClient import MqttClient, mqttConnackMessage, mqttErrorMessage + import UI.PixmapCache class MqttMonitorWidget(QWidget, Ui_MqttMonitorWidget): """ - Class documentation goes here. + Class implementing the MQTT Monitor widget. """ - def __init__(self, parent=None): + def __init__(self, plugin, parent=None): """ Constructor + @param plugin reference to the plug-in object + @type MqttMonitorPlugin @param parent reference to the parent widget @type QWidget """ super(MqttMonitorWidget, self).__init__(parent) self.setupUi(self) + self.__plugin = plugin + + self.__connectedToBroker = False + self.pixmapLabel.setPixmap(UI.PixmapCache.getPixmap( os.path.join("MqttMonitor", "icons", "mqtt48.png"))) + + self.connectButton.setIcon(UI.PixmapCache.getIcon("ircConnect.png")) + self.brokerComboBox.addItems( + self.__plugin.getPreferences("RecentBrokers")) + self.brokerStatusLabel.hide() + + self.__client = MqttClient() + + # connect the MQTT client signals + self.__client.onConnect.connect(self.__brokerConnected) + self.__client.onDisconnected.connect(self.__brokerDisconnected) + self.__client.onMessage.connect(self.__messageReceived) + self.__client.onPublish.connect(self.__messagePublished) + self.__client.onSubscribe.connect(self.__topicSubscribed) + self.__client.onUnsubscribe.connect(self.__topicUnsubscribed) + + ####################################################################### + ## Slots handling MQTT related signals + ####################################################################### + + @pyqtSlot(dict, int) + def __brokerConnected(self, flags, rc): + """ + Private slot to handle being connected to a broker. + + @param flags flags set for the connection + @type dict + @param rc CONNACK result code + @type int + """ + if rc == 0: + self.__connectedToBroker = True + + msg = mqttConnackMessage(rc) + self.__flashBrokerStatusLabel(msg) + + self.connectButton.setIcon(UI.PixmapCache.getIcon("ircDisconnect.png")) + + @pyqtSlot(int) + def __brokerDisconnected(self, rc): + """ + Private slot to handle a disconnection from the broker. + + @param rc MQTT error result code + @type int + """ + self.__connectedToBroker = False + + if rc != 0: + msg = mqttErrorMessage(rc) + else: + msg = self.tr("Connection to Broker shut down cleanly.") + self.__flashBrokerStatusLabel(msg) + + self.connectButton.setIcon(UI.PixmapCache.getIcon("ircConnect.png")) + + self.__client.stopLoop() + + @pyqtSlot(str, bytes, int, bool) + def __messageReceived(self, topic, payload, qos, retain): + """ + Private slot to handle the receipt of a message. + + @param topic topic of the message + @type str + @param payload payload (i.e. data) of the message + @type bytes + @param qos quality of service indicator + @type int + @param retain flag indicating a retained message + @type bool + """ + pass + + @pyqtSlot(int) + def __messagePublished(self, mid): + """ + Private slot to handle a message being published. + + @param mid ID of the published message + @type int + """ + pass + + @pyqtSlot(int, tuple) + def __topicSubscribed(self, mid, grantedQos): + """ + Private slot to handle being subscribed to topics. + + @param mid ID of the subscribe request + @type int + @param grantedQos tuple of granted quality of service + @type tuple of int + """ + pass + + @pyqtSlot(int) + def __topicUnsubscribed(self, mid): + """ + Private slot to handle being unsubcribed from a topic. + + @param mid ID of the unsubscribe request + @type int + """ + pass + + ####################################################################### + ## Slots handling UI interactions + ####################################################################### + + @pyqtSlot() + def __flashBrokerStatusLabel(self, message): + """ + Private slot to show the broker status label with some text for + 5 seconds. + + @param message message to be shown + @type str + """ + self.brokerStatusLabel.setText(message) + self.brokerStatusLabel.show() + QTimer.singleShot(5000, self.brokerStatusLabel.hide) + + @pyqtSlot(str) + def on_brokerComboBox_editTextChanged(self, host): + """ + Private slot to handling entering or selecting a broker host name. + + @param host host name of the broker + @type str + """ + if not self.__connectedToBroker and not host: + self.connectButton.setEnabled(False) + else: + self.connectButton.setEnabled(True) + + @pyqtSlot() + def on_connectButton_clicked(self): + """ + Private slot to handle a connect or disconnect request. + """ + if self.__connectedToBroker: + self.__client.disconnectFromServer() + else: + host = self.brokerComboBox.currentText() + self.__addBrokerToRecent(host) + self.__client.connectToServer(host) # use standard port at 1883 + + ####################################################################### + ## Utility methods + ####################################################################### + + def __addBrokerToRecent(self, host): + """ + Private method to add a host name to the list of recently connected + brokers. + + @param host host name of broker + @type str + """ + brokerList = self.__plugin.getPreferences("RecentBrokers") + if host in brokerList: + brokerList.remove(host) + brokerList.insert(0, host) + self.__plugin.setPreferences("RecentBrokers", brokerList) + + self.brokerComboBox.clear() + self.brokerComboBox.addItems(brokerList)