Sun, 02 Sep 2018 18:29:35 +0200
Finished implementing the connection options dialog.
diff -r 7e0e921dc7ea -r 90d3ebed4cc0 MqttMonitor/MqttClient.py --- a/MqttMonitor/MqttClient.py Sat Sep 01 20:18:11 2018 +0200 +++ b/MqttMonitor/MqttClient.py Sun Sep 02 18:29:35 2018 +0200 @@ -63,6 +63,12 @@ client_id=clientId, clean_session=cleanSession, userdata=None, protocol=mqtt.MQTTv311, transport="tcp") + self.__initCallbacks() + + def __initCallbacks(self): + """ + Private method to initialize the MQTT callback methods. + """ self.__mqttClient.on_connect = \ lambda client, userdata, flags, rc: self.onConnect.emit( flags, rc) @@ -92,6 +98,8 @@ """ self.__mqttClient.reinitialise( client_id=clientId, clean_session=cleanSession, userdata=userdata) + + self.__initCallbacks() def setMaxInflightMessages(self, inflight=20): """
diff -r 7e0e921dc7ea -r 90d3ebed4cc0 MqttMonitor/MqttConnectionOptionsDialog.py --- a/MqttMonitor/MqttConnectionOptionsDialog.py Sat Sep 01 20:18:11 2018 +0200 +++ b/MqttMonitor/MqttConnectionOptionsDialog.py Sun Sep 02 18:29:35 2018 +0200 @@ -1,12 +1,15 @@ # -*- coding: utf-8 -*- +# Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# + """ Module implementing a dialog to enter MQTT connection options. """ from __future__ import unicode_literals -from PyQt5.QtCore import pyqtSlot +from PyQt5.QtCore import pyqtSlot, QUuid from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton from .Ui_MqttConnectionOptionsDialog import Ui_MqttConnectionOptionsDialog @@ -23,7 +26,9 @@ @param client reference to the MQTT client object @type MqttClient @param options dictionary containing the connection options to - populate the dialog with + populate the dialog with. It must have the keys "ClientId", + "Keepalive", "CleanSession", "Username", "Password", "WillTopic", + "WillMessage", "WillQos", "WillRetain". @@type dict @param parent reference to the parent widget @type QWidget @@ -34,7 +39,14 @@ self.__client = client self.__populateDefaults(options=options) - + + @pyqtSlot() + def on_generateIdButton_clicked(self): + """ + Private slot to generate a client ID. + """ + uuid = QUuid.createUuid() + self.clientIdEdit.setText(uuid.toString(QUuid.WithoutBraces)) @pyqtSlot(QAbstractButton) def on_buttonBox_clicked(self, button): @@ -53,6 +65,12 @@ If no options dictionary is given, the dialog will be populated with default values. + + @param options dictionary containing the connection options to populate + the dialog with. It must have the keys "ClientId", "Keepalive", + "CleanSession", "Username", "Password", "WillTopic", "WillMessage", + "WillQos", "WillRetain". + @type dict """ if options is None: options = self.__client.defaultConnectionOptions() @@ -78,7 +96,7 @@ @return dictionary containing the connection options. It has the keys "ClientId", "Keepalive", "CleanSession", "Username", "Password", - "WillTopic", "WillMessage", "WillQos", "WillRetain" + "WillTopic", "WillMessage", "WillQos", "WillRetain". @rtype tuple of (int, dict) """ return {
diff -r 7e0e921dc7ea -r 90d3ebed4cc0 MqttMonitor/MqttConnectionOptionsDialog.ui --- a/MqttMonitor/MqttConnectionOptionsDialog.ui Sat Sep 01 20:18:11 2018 +0200 +++ b/MqttMonitor/MqttConnectionOptionsDialog.ui Sun Sep 02 18:29:35 2018 +0200 @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>400</width> + <width>550</width> <height>600</height> </rect> </property> @@ -37,6 +37,16 @@ </property> </widget> </item> + <item row="0" column="2"> + <widget class="QPushButton" name="generateIdButton"> + <property name="toolTip"> + <string>Press to generate a client ID</string> + </property> + <property name="text"> + <string>Generate</string> + </property> + </widget> + </item> <item row="1" column="0"> <widget class="QLabel" name="label_2"> <property name="text"> @@ -44,7 +54,7 @@ </property> </widget> </item> - <item row="1" column="1"> + <item row="1" column="1" colspan="2"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QSpinBox" name="keepaliveSpinBox"> @@ -80,7 +90,7 @@ </item> </layout> </item> - <item row="2" column="0" colspan="2"> + <item row="2" column="0" colspan="3"> <widget class="QCheckBox" name="cleanSessionCheckBox"> <property name="text"> <string>Clean Session</string> @@ -135,62 +145,45 @@ <property name="title"> <string>Last Will and Testament</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>QoS:</string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="willQosSpinBox"> - <property name="toolTip"> - <string>Enter the desired QoS value</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="maximum"> - <number>2</number> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="willRetainCheckBox"> - <property name="toolTip"> - <string>Select to retain the last will message</string> - </property> - <property name="text"> - <string>Retain</string> - </property> - </widget> - </item> - </layout> - </item> - <item> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> <widget class="QLineEdit" name="willTopicEdit"> <property name="toolTip"> <string>Enter the topic of the last will</string> </property> </widget> </item> - <item> + <item row="0" column="1"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>QoS:</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QSpinBox" name="willQosSpinBox"> + <property name="toolTip"> + <string>Enter the desired QoS value</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="maximum"> + <number>2</number> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QCheckBox" name="willRetainCheckBox"> + <property name="toolTip"> + <string>Select to retain the last will message</string> + </property> + <property name="text"> + <string>Retain</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="4"> <widget class="QPlainTextEdit" name="willMessageEdit"> <property name="maximumSize"> <size> @@ -227,14 +220,15 @@ </customwidgets> <tabstops> <tabstop>clientIdEdit</tabstop> + <tabstop>generateIdButton</tabstop> <tabstop>keepaliveSpinBox</tabstop> <tabstop>cleanSessionCheckBox</tabstop> <tabstop>usernameEdit</tabstop> <tabstop>passwordEdit</tabstop> + <tabstop>willTopicEdit</tabstop> + <tabstop>willMessageEdit</tabstop> <tabstop>willQosSpinBox</tabstop> <tabstop>willRetainCheckBox</tabstop> - <tabstop>willTopicEdit</tabstop> - <tabstop>willMessageEdit</tabstop> </tabstops> <resources/> <connections>
diff -r 7e0e921dc7ea -r 90d3ebed4cc0 MqttMonitor/MqttMonitorWidget.py --- a/MqttMonitor/MqttMonitorWidget.py Sat Sep 01 20:18:11 2018 +0200 +++ b/MqttMonitor/MqttMonitorWidget.py Sun Sep 02 18:29:35 2018 +0200 @@ -164,6 +164,8 @@ self.brokerStatusButton.setEnabled(True) self.__statusLoadValues.clear() + self.__clearBrokerStatusLabels() + self.__setBrokerStatusSubscribed(False) @pyqtSlot(int) def __brokerDisconnected(self, rc): @@ -322,7 +324,11 @@ port = 1883 if host: self.__addBrokerToRecent(host, port) - self.__client.connectToServer(host, port=port) + if self.__connectionOptions is None: + self.__client.connectToServer(host, port=port) + else: + self.__client.connectToServerWithOptions( + host, port=port, options=self.__connectionOptions) @pyqtSlot(str) def on_subscribeTopicEdit_textChanged(self, topic): @@ -403,6 +409,16 @@ self.__updatePublishTopicComboBox() @pyqtSlot() + def on_publishClearButton_clicked(self): + """ + Private slot to clear the publish data fields. + """ + self.publishTopicComboBox.clearEditText() + self.publishPayloadEdit.clear() + self.publishQosSpinBox.setValue(0) + self.publishRetainCheckBox.setChecked(False) + + @pyqtSlot() def on_brokerStatusButton_clicked(self): """ Private slot to subscribe or unsubscribe the broker status topic. @@ -413,20 +429,32 @@ MqttMonitorWidget.BrokerStatusTopic) if rc == 0: # successfully sent - self.__brokerStatusTopicSubscribed = False - self.brokerStatusButton.setText(self.tr("Subscribe")) - self.brokerStatusButton.setToolTip( - self.tr("Press to activate the status display")) + self.__setBrokerStatusSubscribed(False) else: # subscribe status topic rc, _ = self.__client.subscribe( MqttMonitorWidget.BrokerStatusTopic) if rc == 0: # successfully sent - self.__brokerStatusTopicSubscribed = True - self.brokerStatusButton.setText(self.tr("Unsubscribe")) - self.brokerStatusButton.setToolTip( - self.tr("Press to deactivate the status display")) + self.__setBrokerStatusSubscribed(True) + + def __setBrokerStatusSubscribed(self, subscribed): + """ + Private method to set the subscription status for the broker status + topics. + + @param subscribed subscription status for the broker status topics + @type bool + """ + self.__brokerStatusTopicSubscribed = subscribed + if subscribed: + self.brokerStatusButton.setText(self.tr("Unsubscribe")) + self.brokerStatusButton.setToolTip( + self.tr("Press to deactivate the status display")) + else: + self.brokerStatusButton.setText(self.tr("Subscribe")) + self.brokerStatusButton.setToolTip( + self.tr("Press to activate the status display")) ####################################################################### ## Utility methods @@ -470,10 +498,10 @@ else: currentPort = 1883 currentPortStr = "{0:5}".format(currentPort) - portsSet = set([b[1] for b in brokerList]) - portsSet.update([1883, 8883]) + portsSet = {b[1] for b in brokerList} + portsSet.update({1883, 8883}) self.brokerPortComboBox.addItems( - sorted(["{0:5}".format(p) for p in portsSet])) + sorted("{0:5}".format(p) for p in portsSet)) index = self.brokerPortComboBox.findText(currentPortStr) self.brokerPortComboBox.setCurrentIndex(index) @@ -559,6 +587,18 @@ # ignore topics not shown in display pass + def __clearBrokerStatusLabels(self): + """ + Private method to clear the broker status labels. + """ + for statusLabelKey in self.__statusLabelMapping: + if statusLabelKey.startswith( + MqttMonitorWidget.BrokerStatusTopicLoadPrefix): + label = "- / - / -" + else: + label = "-" + self.__statusLabelMapping[statusLabelKey].setText(label) + def __loadDefaultDictFactory(self): """ Private method to populate non-existing load items.
diff -r 7e0e921dc7ea -r 90d3ebed4cc0 MqttMonitor/MqttMonitorWidget.ui --- a/MqttMonitor/MqttMonitorWidget.ui Sat Sep 01 20:18:11 2018 +0200 +++ b/MqttMonitor/MqttMonitorWidget.ui Sun Sep 02 18:29:35 2018 +0200 @@ -280,6 +280,16 @@ <item> <layout class="QHBoxLayout" name="horizontalLayout_12"> <item> + <widget class="QPushButton" name="publishClearButton"> + <property name="toolTip"> + <string>Press to clear the publish data</string> + </property> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item> <spacer name="horizontalSpacer_3"> <property name="orientation"> <enum>Qt::Horizontal</enum>