1 # -*- coding: utf-8 -*- |
1 # -*- coding: utf-8 -*- |
2 |
2 |
|
3 # Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
3 """ |
6 """ |
4 Module implementing MqttMonitorWidget. |
7 Module implementing the MQTT Monitor widget. |
5 """ |
8 """ |
6 |
9 |
7 from __future__ import unicode_literals |
10 from __future__ import unicode_literals |
8 |
11 |
9 import os |
12 import os |
10 |
13 |
11 from PyQt5.QtCore import pyqtSlot |
14 from PyQt5.QtCore import pyqtSlot, QTimer |
12 from PyQt5.QtWidgets import QWidget |
15 from PyQt5.QtWidgets import QWidget |
13 |
16 |
14 from .Ui_MqttMonitorWidget import Ui_MqttMonitorWidget |
17 from .Ui_MqttMonitorWidget import Ui_MqttMonitorWidget |
|
18 |
|
19 from .MqttClient import MqttClient, mqttConnackMessage, mqttErrorMessage |
15 |
20 |
16 import UI.PixmapCache |
21 import UI.PixmapCache |
17 |
22 |
18 |
23 |
19 class MqttMonitorWidget(QWidget, Ui_MqttMonitorWidget): |
24 class MqttMonitorWidget(QWidget, Ui_MqttMonitorWidget): |
20 """ |
25 """ |
21 Class documentation goes here. |
26 Class implementing the MQTT Monitor widget. |
22 """ |
27 """ |
23 def __init__(self, parent=None): |
28 def __init__(self, plugin, parent=None): |
24 """ |
29 """ |
25 Constructor |
30 Constructor |
26 |
31 |
|
32 @param plugin reference to the plug-in object |
|
33 @type MqttMonitorPlugin |
27 @param parent reference to the parent widget |
34 @param parent reference to the parent widget |
28 @type QWidget |
35 @type QWidget |
29 """ |
36 """ |
30 super(MqttMonitorWidget, self).__init__(parent) |
37 super(MqttMonitorWidget, self).__init__(parent) |
31 self.setupUi(self) |
38 self.setupUi(self) |
32 |
39 |
|
40 self.__plugin = plugin |
|
41 |
|
42 self.__connectedToBroker = False |
|
43 |
33 self.pixmapLabel.setPixmap(UI.PixmapCache.getPixmap( |
44 self.pixmapLabel.setPixmap(UI.PixmapCache.getPixmap( |
34 os.path.join("MqttMonitor", "icons", "mqtt48.png"))) |
45 os.path.join("MqttMonitor", "icons", "mqtt48.png"))) |
|
46 |
|
47 self.connectButton.setIcon(UI.PixmapCache.getIcon("ircConnect.png")) |
|
48 self.brokerComboBox.addItems( |
|
49 self.__plugin.getPreferences("RecentBrokers")) |
|
50 self.brokerStatusLabel.hide() |
|
51 |
|
52 self.__client = MqttClient() |
|
53 |
|
54 # connect the MQTT client signals |
|
55 self.__client.onConnect.connect(self.__brokerConnected) |
|
56 self.__client.onDisconnected.connect(self.__brokerDisconnected) |
|
57 self.__client.onMessage.connect(self.__messageReceived) |
|
58 self.__client.onPublish.connect(self.__messagePublished) |
|
59 self.__client.onSubscribe.connect(self.__topicSubscribed) |
|
60 self.__client.onUnsubscribe.connect(self.__topicUnsubscribed) |
|
61 |
|
62 ####################################################################### |
|
63 ## Slots handling MQTT related signals |
|
64 ####################################################################### |
|
65 |
|
66 @pyqtSlot(dict, int) |
|
67 def __brokerConnected(self, flags, rc): |
|
68 """ |
|
69 Private slot to handle being connected to a broker. |
|
70 |
|
71 @param flags flags set for the connection |
|
72 @type dict |
|
73 @param rc CONNACK result code |
|
74 @type int |
|
75 """ |
|
76 if rc == 0: |
|
77 self.__connectedToBroker = True |
|
78 |
|
79 msg = mqttConnackMessage(rc) |
|
80 self.__flashBrokerStatusLabel(msg) |
|
81 |
|
82 self.connectButton.setIcon(UI.PixmapCache.getIcon("ircDisconnect.png")) |
|
83 |
|
84 @pyqtSlot(int) |
|
85 def __brokerDisconnected(self, rc): |
|
86 """ |
|
87 Private slot to handle a disconnection from the broker. |
|
88 |
|
89 @param rc MQTT error result code |
|
90 @type int |
|
91 """ |
|
92 self.__connectedToBroker = False |
|
93 |
|
94 if rc != 0: |
|
95 msg = mqttErrorMessage(rc) |
|
96 else: |
|
97 msg = self.tr("Connection to Broker shut down cleanly.") |
|
98 self.__flashBrokerStatusLabel(msg) |
|
99 |
|
100 self.connectButton.setIcon(UI.PixmapCache.getIcon("ircConnect.png")) |
|
101 |
|
102 self.__client.stopLoop() |
|
103 |
|
104 @pyqtSlot(str, bytes, int, bool) |
|
105 def __messageReceived(self, topic, payload, qos, retain): |
|
106 """ |
|
107 Private slot to handle the receipt of a message. |
|
108 |
|
109 @param topic topic of the message |
|
110 @type str |
|
111 @param payload payload (i.e. data) of the message |
|
112 @type bytes |
|
113 @param qos quality of service indicator |
|
114 @type int |
|
115 @param retain flag indicating a retained message |
|
116 @type bool |
|
117 """ |
|
118 pass |
|
119 |
|
120 @pyqtSlot(int) |
|
121 def __messagePublished(self, mid): |
|
122 """ |
|
123 Private slot to handle a message being published. |
|
124 |
|
125 @param mid ID of the published message |
|
126 @type int |
|
127 """ |
|
128 pass |
|
129 |
|
130 @pyqtSlot(int, tuple) |
|
131 def __topicSubscribed(self, mid, grantedQos): |
|
132 """ |
|
133 Private slot to handle being subscribed to topics. |
|
134 |
|
135 @param mid ID of the subscribe request |
|
136 @type int |
|
137 @param grantedQos tuple of granted quality of service |
|
138 @type tuple of int |
|
139 """ |
|
140 pass |
|
141 |
|
142 @pyqtSlot(int) |
|
143 def __topicUnsubscribed(self, mid): |
|
144 """ |
|
145 Private slot to handle being unsubcribed from a topic. |
|
146 |
|
147 @param mid ID of the unsubscribe request |
|
148 @type int |
|
149 """ |
|
150 pass |
|
151 |
|
152 ####################################################################### |
|
153 ## Slots handling UI interactions |
|
154 ####################################################################### |
|
155 |
|
156 @pyqtSlot() |
|
157 def __flashBrokerStatusLabel(self, message): |
|
158 """ |
|
159 Private slot to show the broker status label with some text for |
|
160 5 seconds. |
|
161 |
|
162 @param message message to be shown |
|
163 @type str |
|
164 """ |
|
165 self.brokerStatusLabel.setText(message) |
|
166 self.brokerStatusLabel.show() |
|
167 QTimer.singleShot(5000, self.brokerStatusLabel.hide) |
|
168 |
|
169 @pyqtSlot(str) |
|
170 def on_brokerComboBox_editTextChanged(self, host): |
|
171 """ |
|
172 Private slot to handling entering or selecting a broker host name. |
|
173 |
|
174 @param host host name of the broker |
|
175 @type str |
|
176 """ |
|
177 if not self.__connectedToBroker and not host: |
|
178 self.connectButton.setEnabled(False) |
|
179 else: |
|
180 self.connectButton.setEnabled(True) |
|
181 |
|
182 @pyqtSlot() |
|
183 def on_connectButton_clicked(self): |
|
184 """ |
|
185 Private slot to handle a connect or disconnect request. |
|
186 """ |
|
187 if self.__connectedToBroker: |
|
188 self.__client.disconnectFromServer() |
|
189 else: |
|
190 host = self.brokerComboBox.currentText() |
|
191 self.__addBrokerToRecent(host) |
|
192 self.__client.connectToServer(host) # use standard port at 1883 |
|
193 |
|
194 ####################################################################### |
|
195 ## Utility methods |
|
196 ####################################################################### |
|
197 |
|
198 def __addBrokerToRecent(self, host): |
|
199 """ |
|
200 Private method to add a host name to the list of recently connected |
|
201 brokers. |
|
202 |
|
203 @param host host name of broker |
|
204 @type str |
|
205 """ |
|
206 brokerList = self.__plugin.getPreferences("RecentBrokers") |
|
207 if host in brokerList: |
|
208 brokerList.remove(host) |
|
209 brokerList.insert(0, host) |
|
210 self.__plugin.setPreferences("RecentBrokers", brokerList) |
|
211 |
|
212 self.brokerComboBox.clear() |
|
213 self.brokerComboBox.addItems(brokerList) |