Fri, 23 Jul 2021 19:48:14 +0200
Made the default MQTT protocol a configuration item.
diff -r 9a4c9b7f078c -r 36ec7431ad04 MqttMonitor/ConfigurationPage/MqttPage.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MqttMonitor/ConfigurationPage/MqttPage.py Fri Jul 23 19:48:14 2021 +0200 @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the MQTT Monitor configuration page. +""" + +from Preferences.ConfigurationPages.ConfigurationPageBase import ( + ConfigurationPageBase +) + +from .Ui_MqttPage import Ui_MqttPage + +from ..MqttProtocols import MqttProtocols + + +class MqttPage(ConfigurationPageBase, Ui_MqttPage): + """ + Class implementing the MQTT Monitor configuration page. + """ + def __init__(self, plugin): + """ + Constructor + + @param plugin reference to the plugin object + @type RefactoringRopePlugin + """ + ConfigurationPageBase.__init__(self) + self.setupUi(self) + self.setObjectName("MqttPage") + + self.__plugin = plugin + + # set initial values + protocol = self.__plugin.getPreferences("DefaultProtocol") + self.mqttv31Button.setChecked( + protocol == MqttProtocols.MQTTv31) + self.mqttv311Button.setChecked( + protocol == MqttProtocols.MQTTv311) + self.mqttv5Button.setChecked( + protocol == MqttProtocols.MQTTv5) + self.recentBrokersSpinBox.setValue( + self.__plugin.getPreferences("RecentBrokersNumber")) + self.recentTopicsSpinBox.setValue( + self.__plugin.getPreferences("RecentTopicsNumber")) + + def save(self): + """ + Public slot to save the Rope Autocompletion configuration. + """ + if self.mqttv31Button.isChecked(): + protocol = MqttProtocols.MQTTv31 + elif self.mqttv311Button.isChecked(): + protocol = MqttProtocols.MQTTv311 + elif self.mqttv5Button.isChecked(): + protocol = MqttProtocols.MQTTv5 + else: + # should never happen + protocol = MqttProtocols.MQTTv311 + + self.__plugin.setPreferences("DefaultProtocol", protocol) + self.__plugin.setPreferences("RecentBrokersNumber", + self.recentBrokersSpinBox.value()) + self.__plugin.setPreferences("RecentTopicsNumber", + self.recentTopicsSpinBox.value())
diff -r 9a4c9b7f078c -r 36ec7431ad04 MqttMonitor/ConfigurationPage/MqttPage.ui --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MqttMonitor/ConfigurationPage/MqttPage.ui Fri Jul 23 19:48:14 2021 +0200 @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MqttPage</class> + <widget class="QWidget" name="MqttPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>316</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="headerLabel"> + <property name="text"> + <string><b>Configure MQTT Monitor</b></string> + </property> + </widget> + </item> + <item> + <widget class="Line" name="line15"> + <property name="frameShape"> + <enum>QFrame::HLine</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_5"> + <property name="title"> + <string>Default MQTT Protocol</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QRadioButton" name="mqttv31Button"> + <property name="toolTip"> + <string>Select to use the MQTT 3.1 protocol</string> + </property> + <property name="text"> + <string>v 3.1</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="mqttv311Button"> + <property name="toolTip"> + <string>Select to use the MQTT 3.1.1 protocol</string> + </property> + <property name="text"> + <string>v 3.1.1</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="mqttv5Button"> + <property name="toolTip"> + <string>Select to use the MQTT 5.0 protocol</string> + </property> + <property name="text"> + <string>v 5.0</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_7"> + <property name="title"> + <string>Recent Brokers</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Number of recent brokers:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="recentBrokersSpinBox"> + <property name="toolTip"> + <string>Enter the number of recent brokers to remember</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="minimum"> + <number>5</number> + </property> + <property name="maximum"> + <number>50</number> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>138</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_8"> + <property name="title"> + <string>Recent Topics</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Number of recent topics:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="recentTopicsSpinBox"> + <property name="toolTip"> + <string>Enter the number of recent topics to remember</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="minimum"> + <number>5</number> + </property> + <property name="maximum"> + <number>50</number> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>31</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <tabstops> + <tabstop>mqttv31Button</tabstop> + <tabstop>mqttv311Button</tabstop> + <tabstop>mqttv5Button</tabstop> + <tabstop>recentBrokersSpinBox</tabstop> + <tabstop>recentTopicsSpinBox</tabstop> + </tabstops> + <resources/> + <connections/> +</ui>
diff -r 9a4c9b7f078c -r 36ec7431ad04 MqttMonitor/ConfigurationPage/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MqttMonitor/ConfigurationPage/__init__.py Fri Jul 23 19:48:14 2021 +0200 @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package implementing the MQTT Monitor page of the configuration dialog. +"""
diff -r 9a4c9b7f078c -r 36ec7431ad04 MqttMonitor/MqttClient.py --- a/MqttMonitor/MqttClient.py Fri Jul 23 17:48:22 2021 +0200 +++ b/MqttMonitor/MqttClient.py Fri Jul 23 19:48:14 2021 +0200 @@ -7,8 +7,6 @@ Module implementing a PyQt wrapper around the paho MQTT client. """ -import enum - from PyQt6.QtCore import ( pyqtSignal, pyqtSlot, QObject, QCoreApplication, QTimer ) @@ -19,14 +17,7 @@ from Utilities.crypto import pwConvert - -class MqttProtocols(enum.IntEnum): - """ - Class defining the supported MQTT protocol versions. - """ - MQTTv31 = mqtt.MQTTv31 - MQTTv311 = mqtt.MQTTv311 - MQTTv5 = mqtt.MQTTv5 +from .MqttProtocols import MqttProtocols class MqttClient(QObject): @@ -489,7 +480,7 @@ properties=properties, clearWill=clearWill) else: - keepalive = self.defaultConnectionOptions["Keepalive"] + keepalive = self.defaultConnectionOptions()["Keepalive"] self.connectToServer(host, port=port, keepalive=keepalive, bindAddress=bindAddress, clearWill=clearWill) @@ -507,9 +498,11 @@ "TlsCaCert", "TlsClientCert", "TlsClientKey", "UserProperties". @rtype dict """ + from PluginMqttMonitor import mqttPluginObject + return { "ClientId": "ERIC7_MQTT_MONITOR_CLIENT", - "Protocol": MqttProtocols.MQTTv311, + "Protocol": mqttPluginObject.getPreferences("DefaultProtocol"), "ConnectionTimeout": MqttClient.DefaultConnectTimeout, "Keepalive": 60, "CleanSession": True,
diff -r 9a4c9b7f078c -r 36ec7431ad04 MqttMonitor/MqttConnectionOptionsDialog.py --- a/MqttMonitor/MqttConnectionOptionsDialog.py Fri Jul 23 17:48:22 2021 +0200 +++ b/MqttMonitor/MqttConnectionOptionsDialog.py Fri Jul 23 19:48:14 2021 +0200 @@ -17,7 +17,8 @@ from .Ui_MqttConnectionOptionsDialog import Ui_MqttConnectionOptionsDialog -from .MqttClient import MqttClient, MqttProtocols +from .MqttClient import MqttClient +from .MqttProtocols import MqttProtocols from Utilities.crypto import pwConvert import UI.PixmapCache @@ -271,6 +272,7 @@ elif self.mqttv5Button.isChecked(): protocol = MqttProtocols.MQTTv5 else: + # should never happen protocol = MqttProtocols.MQTTv311 if protocol == MqttProtocols.MQTTv5:
diff -r 9a4c9b7f078c -r 36ec7431ad04 MqttMonitor/MqttConnectionProfilesDialog.py --- a/MqttMonitor/MqttConnectionProfilesDialog.py Fri Jul 23 17:48:22 2021 +0200 +++ b/MqttMonitor/MqttConnectionProfilesDialog.py Fri Jul 23 19:48:14 2021 +0200 @@ -21,7 +21,8 @@ from .Ui_MqttConnectionProfilesDialog import Ui_MqttConnectionProfilesDialog -from .MqttClient import MqttClient, MqttProtocols +from .MqttClient import MqttClient +from .MqttProtocols import MqttProtocols import UI.PixmapCache from Utilities.crypto import pwConvert @@ -275,6 +276,7 @@ elif self.mqttv5Button.isChecked(): protocol = MqttProtocols.MQTTv5 else: + # should never happen protocol = MqttProtocols.MQTTv311 if protocol == MqttProtocols.MQTTv5: @@ -540,6 +542,7 @@ elif self.mqttv5Button.isChecked(): protocol = MqttProtocols.MQTTv5 else: + # should never happen protocol = MqttProtocols.MQTTv311 connectionProfile = self.__defaultProfile()
diff -r 9a4c9b7f078c -r 36ec7431ad04 MqttMonitor/MqttMonitorWidget.py --- a/MqttMonitor/MqttMonitorWidget.py Fri Jul 23 17:48:22 2021 +0200 +++ b/MqttMonitor/MqttMonitorWidget.py Fri Jul 23 19:48:14 2021 +0200 @@ -22,10 +22,10 @@ from .Ui_MqttMonitorWidget import Ui_MqttMonitorWidget from .MqttClient import ( - MqttClient, MqttProtocols, mqttConnackMessage, mqttErrorMessage, - mqttLogLevelString + MqttClient, mqttConnackMessage, mqttErrorMessage, mqttLogLevelString ) from .MqttReasonCodes import mqttReasonCode +from .MqttProtocols import MqttProtocols import UI.PixmapCache import Utilities @@ -214,10 +214,8 @@ self.__statusLoadValues = collections.defaultdict( self.__loadDefaultDictFactory) - # TODO: make MQTT default protocol version a configuration option - # (config page) def __createClient(self, clientId="", cleanSession=None, - protocol=MqttProtocols.MQTTv311): + protocol=None): """ Private method to instantiate a MQTT client for a given protocol. @@ -225,12 +223,14 @@ @type str @param cleanSession flag indicating to start a clean session @type bool - @param protocol MQTT protocol version to be used (defaults to - MqttProtocols.MQTTv311) - @type MqttProtocols (optional) + @param protocol MQTT protocol version to be used (defaults to None) + @type MqttProtocols or int (optional) @return created and connected MQTT client object @rtype MqttClient """ + if protocol is None: + protocol = self.__plugin.getPreferences("DefaultProtocol") + client = MqttClient(clientId=clientId, cleanSession=cleanSession, protocol=protocol) @@ -1342,7 +1342,8 @@ try: protocol = connectionProfile["Protocol"] except KeyError: - protocol = MqttProtocols.MQTTv311 + protocol = MqttProtocols( + self.__plugin.getPreferences("DefaultProtocol")) self.brokerStatusLabel.setText( self.tr("Connecting to {0}:{1} ...").format(
diff -r 9a4c9b7f078c -r 36ec7431ad04 MqttMonitor/MqttProtocols.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MqttMonitor/MqttProtocols.py Fri Jul 23 19:48:14 2021 +0200 @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing an enum defining the supported MQTT protocol versions. +""" + +import enum + +try: + import paho.mqtt.client as mqtt + + class MqttProtocols(enum.IntEnum): + """ + Class defining the supported MQTT protocol versions. + """ + MQTTv31 = mqtt.MQTTv31 + MQTTv311 = mqtt.MQTTv311 + MQTTv5 = mqtt.MQTTv5 +except ImportError: + # define the enum with known values + class MqttProtocols(enum.IntEnum): + """ + Class defining the supported MQTT protocol versions. + """ + MQTTv31 = 3 + MQTTv311 = 4 + MQTTv5 = 5
diff -r 9a4c9b7f078c -r 36ec7431ad04 PluginMqttMonitor.epj --- a/PluginMqttMonitor.epj Fri Jul 23 17:48:22 2021 +0200 +++ b/PluginMqttMonitor.epj Fri Jul 23 19:48:14 2021 +0200 @@ -155,7 +155,8 @@ "MqttMonitor/MqttConnectionOptionsDialog.ui", "MqttMonitor/MqttConnectionProfilesDialog.ui", "MqttMonitor/MqttMonitorWidget.ui", - "MqttMonitor/MqttUserPropertiesEditor.ui" + "MqttMonitor/MqttUserPropertiesEditor.ui", + "MqttMonitor/ConfigurationPage/MqttPage.ui" ], "HASH": "8b864e3e4a3495e242eae3cb3ef4dc8522bf6ce7", "IDLPARAMS": { @@ -216,7 +217,10 @@ "PluginMqttMonitor.py", "__init__.py", "MqttMonitor/MqttReasonCodes.py", - "MqttMonitor/MqttUserPropertiesEditor.py" + "MqttMonitor/MqttUserPropertiesEditor.py", + "MqttMonitor/ConfigurationPage/__init__.py", + "MqttMonitor/ConfigurationPage/MqttPage.py", + "MqttMonitor/MqttProtocols.py" ], "SPELLEXCLUDES": "", "SPELLLANGUAGE": "en", @@ -282,4 +286,4 @@ "VCSOTHERDATA": {}, "VERSION": "" } -} +} \ No newline at end of file
diff -r 9a4c9b7f078c -r 36ec7431ad04 PluginMqttMonitor.py --- a/PluginMqttMonitor.py Fri Jul 23 17:48:22 2021 +0200 +++ b/PluginMqttMonitor.py Fri Jul 23 19:48:14 2021 +0200 @@ -19,6 +19,8 @@ import UI.PixmapCache import Preferences +from MqttMonitor.MqttProtocols import MqttProtocols + # Start-Of-Header name = "MQTT Monitor Plugin" author = "Detlev Offenbach <detlev@die-offenbachs.de>" @@ -41,7 +43,44 @@ # End-Of-Header error = "" + +mqttPluginObject = None + + +def createMqttPage(configDlg): + """ + Module function to create the autocompletion configuration page. + @param configDlg reference to the configuration dialog + @type ConfigurationWidget + @return reference to the configuration page + @rtype AutoCompletionRopePage + """ + global mqttPluginObject + from MqttMonitor.ConfigurationPage.MqttPage import MqttPage + + page = MqttPage(mqttPluginObject) + return page + + +def getConfigData(): + """ + Module function returning data as required by the configuration dialog. + + @return dictionary containing the relevant data + @rtype dict + """ + usesDarkPalette = ericApp().usesDarkPalette() + iconSuffix = "dark" if usesDarkPalette else "light" + + return { + "mqttPage": [ + QCoreApplication.translate("MqttMonitorPlugin", "MQTT Monitor"), + os.path.join( + "MqttMonitor", "icons", "mqtt22-{0}".format(iconSuffix)), + createMqttPage, None, None], + } + def exeDisplayData(): """ @@ -101,6 +140,9 @@ # __IGNORE_WARNING_M613__ "UnsubscribeProperties": "{}", # JSON formatted empty dict # __IGNORE_WARNING_M613__ + "DefaultProtocol": MqttProtocols.MQTTv311, + "RecentBrokersNumber": 20, + "RecentTopicsNumber": 20, } self.__translator = None @@ -119,8 +161,10 @@ @return tuple of None and activation status @rtype tuple of (None, bool) """ - global error + global error, mqttPluginObject error = "" # clear previous error + mqttPluginObject = self + try: import paho.mqtt # __IGNORE_WARNING__ @@ -218,11 +262,18 @@ @return value of the requested setting @rtype Any """ - if key in ["RecentBrokersWithPort", "BrokerProfiles", + if key in ("RecentBrokersWithPort", "BrokerProfiles", "SubscribeProperties", "UnsubscribeProperties", - "PublishProperties"]: + "PublishProperties"): return json.loads(Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key])) + elif key in ("DefaultProtocol", ): + return MqttProtocols(int(Preferences.Prefs.settings.value( + self.PreferencesKey + "/" + key, self.__defaults[key]))) + elif key in ("DefaultProtocol", "RecentBrokersNumber", + "RecentTopicsNumber"): + return int(Preferences.Prefs.settings.value( + self.PreferencesKey + "/" + key, self.__defaults[key])) else: return Preferences.Prefs.settings.value( self.PreferencesKey + "/" + key, self.__defaults[key]) @@ -236,11 +287,14 @@ @param value value to be set @type Any """ - if key in ["RecentBrokersWithPort", "BrokerProfiles", + if key in ("RecentBrokersWithPort", "BrokerProfiles", "SubscribeProperties", "UnsubscribeProperties", - "PublishProperties"]: + "PublishProperties"): Preferences.Prefs.settings.setValue( self.PreferencesKey + "/" + key, json.dumps(value)) + elif key in ("DefaultProtocol", ): + Preferences.Prefs.settings.setValue( + self.PreferencesKey + "/" + key, int(value)) else: Preferences.Prefs.settings.setValue( self.PreferencesKey + "/" + key, value)