Skip to content

Commit dbe6215

Browse files
committed
v1.3 using QThread
1 parent d4c0f37 commit dbe6215

File tree

5 files changed

+83
-32
lines changed

5 files changed

+83
-32
lines changed

Uploader_GUI/RTK_Firmware_Uploader_GUI.py

Lines changed: 83 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,17 @@
3535

3636
from typing import Iterator, Tuple
3737

38-
from PyQt5.QtCore import QSettings, QProcess, QTimer, Qt, QIODevice, pyqtSlot
38+
from PyQt5.QtCore import QSettings, QProcess, QTimer, Qt, QIODevice, pyqtSlot, \
39+
QObject, QThread, pyqtSignal
3940
from PyQt5.QtWidgets import QWidget, QLabel, QComboBox, QGridLayout, \
4041
QPushButton, QApplication, QLineEdit, QFileDialog, QPlainTextEdit, \
4142
QAction, QActionGroup, QMenu, QMenuBar, QMainWindow, QMessageBox
4243
from PyQt5.QtGui import QCloseEvent, QTextCursor, QIcon, QFont
43-
from PyQt5.QtSerialPort import QSerialPortInfo, QSerialPortInfo
44+
from PyQt5.QtSerialPort import QSerialPortInfo
4445

4546
import sys
4647
import os
48+
from time import sleep
4749

4850
import esptool
4951
from esptool import ESPLoader
@@ -55,9 +57,10 @@
5557
# Setting constants
5658
SETTING_PORT_NAME = 'port_name'
5759
SETTING_FILE_LOCATION = 'file_location'
60+
SETTING_PARTITION_LOCATION = 'partition_location'
5861
SETTING_BAUD_RATE = 'baud'
5962

60-
guiVersion = 'v1.2'
63+
guiVersion = 'v1.3'
6164

6265
def gen_serial_ports() -> Iterator[Tuple[str, str, str]]:
6366
"""Return all available serial ports."""
@@ -95,6 +98,19 @@ def flush(self) -> None:
9598
def isatty(self):
9699
return True
97100

101+
class ESPTool(QObject):
102+
finished = pyqtSignal()
103+
104+
def run(self, command):
105+
"""Run esptool in a separate thread to stop the GUI from freezing"""
106+
try:
107+
esptool.main(command)
108+
except (ValueError, IOError, FatalError, ImportError, NotImplementedInROMError, UnsupportedCommandError, NotSupportedError, RuntimeError) as err:
109+
print(str(err))
110+
except:
111+
pass
112+
self.finished.emit()
113+
98114
# noinspection PyArgumentList
99115

100116
class MainWidget(QWidget):
@@ -103,13 +119,10 @@ class MainWidget(QWidget):
103119
def __init__(self, parent: QWidget = None) -> None:
104120
super().__init__(parent)
105121

106-
self.timer=QTimer()
107-
self.timer.timeout.connect(self.repaintMessageBox)
108-
109122
# File location line edit
110-
self.msg_label = QLabel(self.tr('Firmware File:'))
123+
self.file_label = QLabel(self.tr('Firmware File:'))
111124
self.fileLocation_lineedit = QLineEdit()
112-
self.msg_label.setBuddy(self.fileLocation_lineedit)
125+
self.file_label.setBuddy(self.fileLocation_lineedit)
113126
self.fileLocation_lineedit.setEnabled(False)
114127
self.fileLocation_lineedit.returnPressed.connect(self.on_browse_btn_pressed)
115128

@@ -118,6 +131,18 @@ def __init__(self, parent: QWidget = None) -> None:
118131
self.browse_btn.setEnabled(True)
119132
self.browse_btn.pressed.connect(self.on_browse_btn_pressed)
120133

134+
# Partition file location line edit
135+
self.partition_label = QLabel(self.tr('Partition File:'))
136+
self.partitionFileLocation_lineedit = QLineEdit()
137+
self.partition_label.setBuddy(self.partitionFileLocation_lineedit)
138+
self.partitionFileLocation_lineedit.setEnabled(False)
139+
self.partitionFileLocation_lineedit.returnPressed.connect(self.on_partition_browse_btn_pressed)
140+
141+
# Browse for new file button
142+
self.partition_browse_btn = QPushButton(self.tr('Browse'))
143+
self.partition_browse_btn.setEnabled(True)
144+
self.partition_browse_btn.pressed.connect(self.on_partition_browse_btn_pressed)
145+
121146
# Port Combobox
122147
self.port_label = QLabel(self.tr('COM Port:'))
123148
self.port_combobox = QComboBox()
@@ -152,20 +177,24 @@ def __init__(self, parent: QWidget = None) -> None:
152177
# Arrange Layout
153178
layout = QGridLayout()
154179

155-
layout.addWidget(self.msg_label, 1, 0)
180+
layout.addWidget(self.file_label, 1, 0)
156181
layout.addWidget(self.fileLocation_lineedit, 1, 1)
157182
layout.addWidget(self.browse_btn, 1, 2)
158183

159-
layout.addWidget(self.port_label, 2, 0)
160-
layout.addWidget(self.port_combobox, 2, 1)
161-
layout.addWidget(self.refresh_btn, 2, 2)
184+
layout.addWidget(self.partition_label, 2, 0)
185+
layout.addWidget(self.partitionFileLocation_lineedit, 2, 1)
186+
layout.addWidget(self.partition_browse_btn, 2, 2)
187+
188+
layout.addWidget(self.port_label, 3, 0)
189+
layout.addWidget(self.port_combobox, 3, 1)
190+
layout.addWidget(self.refresh_btn, 3, 2)
162191

163-
layout.addWidget(self.baud_label, 3, 0)
164-
layout.addWidget(self.baud_combobox, 3, 1)
165-
layout.addWidget(self.upload_btn, 3, 2)
192+
layout.addWidget(self.baud_label, 4, 0)
193+
layout.addWidget(self.baud_combobox, 4, 1)
194+
layout.addWidget(self.upload_btn, 4, 2)
166195

167-
layout.addWidget(self.messages_label, 4, 0)
168-
layout.addWidget(self.messageBox, 5, 0, 5, 3)
196+
layout.addWidget(self.messages_label, 5, 0)
197+
layout.addWidget(self.messageBox, 6, 0, 5, 3)
169198

170199
self.setLayout(layout)
171200

@@ -180,16 +209,6 @@ def writeMessage(self, msg) -> None:
180209
self.messageBox.ensureCursorVisible()
181210
self.messageBox.repaint()
182211

183-
def startTimer(self) -> None:
184-
self.timer.start(1000)
185-
186-
def endTimer(self) -> None:
187-
self.timer.stop()
188-
189-
def repaintMessageBox(self) -> None:
190-
self.messageBox.ensureCursorVisible()
191-
self.messageBox.repaint()
192-
193212
def _load_settings(self) -> None:
194213
"""Load settings on startup."""
195214
port_name = self.settings.value(SETTING_PORT_NAME)
@@ -202,6 +221,12 @@ def _load_settings(self) -> None:
202221
if lastFile is not None:
203222
self.fileLocation_lineedit.setText(lastFile)
204223

224+
lastFile = self.settings.value(SETTING_PARTITION_LOCATION)
225+
if lastFile is not None:
226+
self.partitionFileLocation_lineedit.setText(lastFile)
227+
else:
228+
self.partitionFileLocation_lineedit.setText(resource_path("RTK_Surveyor.ino.partitions.bin"))
229+
205230
baud = self.settings.value(SETTING_BAUD_RATE)
206231
if baud is not None:
207232
index = self.baud_combobox.findData(baud)
@@ -212,6 +237,7 @@ def _save_settings(self) -> None:
212237
"""Save settings on shutdown."""
213238
self.settings.setValue(SETTING_PORT_NAME, self.port)
214239
self.settings.setValue(SETTING_FILE_LOCATION, self.theFileName)
240+
self.settings.setValue(SETTING_PARTITION_LOCATION, self.thePartitionFileName)
215241
self.settings.setValue(SETTING_BAUD_RATE, self.baudRate)
216242

217243
def _clean_settings(self) -> None:
@@ -264,15 +290,18 @@ def theFileName(self) -> str:
264290
"""Return the file name."""
265291
return self.fileLocation_lineedit.text()
266292

293+
@property
294+
def thePartitionFileName(self) -> str:
295+
"""Return the partition file name."""
296+
return self.partitionFileLocation_lineedit.text()
297+
267298
def closeEvent(self, event: QCloseEvent) -> None:
268299
"""Handle Close event of the Widget."""
269300
try:
270301
self._save_settings()
271302
except:
272303
pass
273304

274-
self.endTimer()
275-
276305
event.accept()
277306

278307
def on_refresh_btn_pressed(self) -> None:
@@ -291,6 +320,18 @@ def on_browse_btn_pressed(self) -> None:
291320
if fileName:
292321
self.fileLocation_lineedit.setText(fileName)
293322

323+
def on_partition_browse_btn_pressed(self) -> None:
324+
"""Open dialog to select partition bin file."""
325+
options = QFileDialog.Options()
326+
fileName, _ = QFileDialog.getOpenFileName(
327+
None,
328+
"Select Partition File",
329+
"",
330+
"Parition Files (*.bin);;All Files (*)",
331+
options=options)
332+
if fileName:
333+
self.partitionFileLocation_lineedit.setText(fileName)
334+
294335
def on_upload_btn_pressed(self) -> None:
295336
"""Upload the firmware"""
296337
portAvailable = False
@@ -327,22 +368,32 @@ def on_upload_btn_pressed(self) -> None:
327368
command.extend(["--baud",self.baudRate])
328369
command.extend(["--before","default_reset","--after","hard_reset","write_flash","-z","--flash_mode","dio","--flash_freq","80m","--flash_size","detect"])
329370
command.extend(["0x1000",resource_path("RTK_Surveyor.ino.bootloader.bin")])
330-
command.extend(["0x8000",resource_path("RTK_Surveyor.ino.partitions.bin")])
371+
command.extend(["0x8000",self.thePartitionFileName])
331372
command.extend(["0xe000",resource_path("boot_app0.bin")])
332373
command.extend(["0x10000",self.theFileName])
333374

334375
self.writeMessage("Command: esptool.main(%s)\n\n" % " ".join(command))
335376

336377
#print("python esptool.py %s\n\n" % " ".join(command)) # Useful for debugging - cut and paste into a command prompt
337378

338-
self.startTimer()
379+
self.thread = QThread()
380+
self.espTool = ESPTool()
381+
self.espTool.moveToThread(self.thread)
382+
self.thread.started.connect(self.espTool.run(command))
383+
self.thread.finished.connect(lambda: self.upload_btn.setEnabled(True))
384+
self.espTool.finished.connect(self.thread.quit)
385+
self.espTool.finished.connect(self.espTool.deleteLater)
386+
self.thread.finished.connect(self.thread.deleteLater)
387+
self.upload_btn.setEnabled(False)
388+
#self.thread.start()
339389

340390
try:
341391
esptool.main(command)
342392
except (ValueError, IOError, FatalError, ImportError, NotImplementedInROMError, UnsupportedCommandError, NotSupportedError, RuntimeError) as err:
343393
self.writeMessage(str(err))
394+
except:
395+
pass
344396

345-
self.endTimer()
346397

347398
if __name__ == '__main__':
348399
from sys import exit as sysExit
Binary file not shown.
53.3 KB
Binary file not shown.
-31.8 MB
Binary file not shown.
-31.8 MB
Binary file not shown.

0 commit comments

Comments
 (0)