Projekt

Obecné

Profil

Stáhnout (6.19 KB) Statistiky
| Větev: | Tag: | Revize:
1
import logging
2

    
3
import matplotlib.pyplot as plt
4
from PyQt5 import QtCore
5
from PyQt5 import QtGui
6
from PyQt5.QtCore import QSize, QThread, QObject, pyqtSignal, QSettings
7
from PyQt5.QtWidgets import QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QScrollArea, QGridLayout
8
from PyQt5.QtWidgets import QMenuBar, QAction, QPushButton
9
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
10

    
11
from aswi2021vochomurka.model.Message import Message
12
from aswi2021vochomurka.service.mqtt.mqtt_subscriber import MQTTSubscriber
13
from aswi2021vochomurka.service.subscriber import Subscriber
14
from aswi2021vochomurka.service.subscriber_callback import SubscriberCallback
15
from aswi2021vochomurka.service.subscriber_params import SubscriberParams, ConnectionParams
16
from aswi2021vochomurka.view.logger_view import LoggerView
17
from aswi2021vochomurka.view.settings import SettingsDialog, DEFAULT_HOST, DEFAULT_PORT, DEFAULT_KEEPALIVE, \
18
    DEFAULT_ANONYMOUS, DEFAULT_USERNAME, DEFAULT_TIMEOUT, DEFAULT_TOPICS, get_settings
19

    
20

    
21
class Worker(QObject, SubscriberCallback):
22
    connected = pyqtSignal()
23
    disconnected = pyqtSignal()
24
    error = pyqtSignal(Exception)
25
    newMessage = pyqtSignal(Message)
26
    subscriber: Subscriber = None
27
    params: SubscriberParams
28

    
29
    def __init__(self, params: SubscriberParams) -> None:
30
        super().__init__()
31
        self.params = params
32

    
33
    def start(self):
34
        self.subscriber = MQTTSubscriber(self, self.params)
35
        self.subscriber.start()
36

    
37
    def stop(self):
38
        self.subscriber.stop()
39

    
40
    def onConnected(self):
41
        self.connected.emit()
42

    
43
    def onDisconnected(self):
44
        self.disconnected.emit()
45

    
46
    def onError(self):
47
        pass
48

    
49
    def onMessage(self, message: Message):
50
        self.newMessage.emit(message)
51
        # self.window.plot(message)
52

    
53
    def onCloseTopic(self, topic: str):
54
        pass
55

    
56

    
57
class MainView(QMainWindow):
58
    worker: Worker = None
59
    workerThread: QThread = None
60

    
61
    def __init__(self):
62
        super(MainView, self).__init__()
63

    
64
        self.chartsNum = 0
65
        self.arrayData = []
66

    
67
        self.dataIndex = 0
68
        self.dataDict = {}
69

    
70
        self.canvasDict = {}
71
        self.figureDict = {}
72

    
73
        # self.toolbar = NavigationToolbar(self.canvas, self)
74

    
75
        # self.setMinimumSize(QSize(440, 240))
76
        self.setMinimumSize(QSize(1200, 800))
77
        self.setWindowTitle("MQTT client")
78

    
79
        logger = self._createLoggerView()
80
        layout = QVBoxLayout()
81
        layout.addWidget(logger.widget)
82
        # layout.addWidget(self.toolbar)
83

    
84
        widget = QWidget()
85
        widget.setLayout(layout)
86
        self.setCentralWidget(widget)
87
        self._createMenuBar()
88

    
89
        scrollArea = QScrollArea(self)
90
        scrollArea.setWidgetResizable(True)
91
        scrollContent = QWidget()
92
        self.grid = QGridLayout(scrollContent)
93
        scrollArea.setWidget(scrollContent)
94
        layout.addWidget(scrollArea)
95

    
96
        self.init_subscriber()
97

    
98
    def _createLoggerView(self):
99
        logger = LoggerView(self)
100
        formatter = logging.Formatter('%(asctime)s %(message)s', '%H:%M')
101
        logger.setFormatter(formatter)
102
        logger.setLevel(logging.INFO)
103
        logging.getLogger('').addHandler(logger)
104
        return logger
105

    
106
    def _createMenuBar(self):
107
        menuBar = QMenuBar(self)
108
        settingsAction = QAction("&Settings", self)
109
        settingsAction.triggered.connect(self.settings)
110
        menuBar.addAction(settingsAction)
111
        self.setMenuBar(menuBar)
112

    
113
    def plot(self, message: Message):
114
        if message.topic in self.dataDict:
115
            self.dataDict[message.topic].append(message.value)
116

    
117
            figure = self.figureDict[message.topic]
118
            figure.clear()
119

    
120
            plt.figure(figure.number)
121
            plt.plot(self.dataDict[message.topic])
122

    
123
            self.canvasDict[message.topic].draw()
124
        else:
125
            self.dataDict[message.topic] = [message.value]
126

    
127
            figure = plt.figure(figsize=[500, 500])
128
            canvas = FigureCanvas(figure)
129
            layout = QHBoxLayout()
130

    
131
            plt.plot(self.dataDict[message.topic])
132

    
133
            self.canvasDict[message.topic] = canvas
134
            self.figureDict[message.topic] = figure
135

    
136
            widget = QWidget()
137
            widget.setLayout(layout)
138
            button = QPushButton(':')
139
            button.setFixedSize(QSize(40, 40))
140
            layout.addWidget(canvas)
141
            layout.addWidget(button)
142
            layout.setAlignment(button, QtCore.Qt.AlignTop)
143
            widget.setMinimumSize(QSize(500, 500))
144

    
145
            self.grid.addWidget(widget, int(self.chartsNum / 2), self.chartsNum % 2)
146

    
147
            self.chartsNum += 1
148

    
149
    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
150
        self.worker.stop()
151

    
152
    def settings(self):
153
        dialog = SettingsDialog()
154
        if dialog.exec_():
155
            self.reconnect()
156

    
157
    def disconnect(self):
158
        self.worker.stop()
159
        self.workerThread.quit()
160
        self.workerThread.wait()
161

    
162
    def reconnect(self):
163
        self.disconnect()
164
        self.worker.params = self.getConfigParams()
165
        self.workerThread.start()
166

    
167
    def init_subscriber(self):
168
        self.workerThread = QThread()
169
        self.worker = Worker(self.getConfigParams())
170
        self.worker.moveToThread(self.workerThread)
171
        self.workerThread.started.connect(self.worker.start)
172
        self.worker.newMessage.connect(
173
            lambda message: self.plot(message)
174
        )
175
        self.worker.window = self
176
        self.workerThread.start()
177

    
178
    def getConfigParams(self) -> SubscriberParams:
179
        settings = get_settings()
180

    
181
        connection = ConnectionParams(
182
            settings.value("connection_host", DEFAULT_HOST, str),
183
            settings.value("connection_port", DEFAULT_PORT, int),
184
            settings.value("connection_keepalive", DEFAULT_KEEPALIVE, int)
185
        )
186

    
187
        params = SubscriberParams(
188
            settings.value("topics_items", DEFAULT_TOPICS),
189
            settings.value("topics_timeout", DEFAULT_TIMEOUT, int),
190
            connection,
191
            settings.value("connection_anonymous", DEFAULT_ANONYMOUS, bool),
192
            settings.value("connection_username", DEFAULT_USERNAME, str),
193
            settings.value("connection_password", DEFAULT_USERNAME, str),
194
        )
195

    
196
        return params
(3-3/4)