Skip to content

Commit ab9d6a7

Browse files
committed
Uploader GUI v1.3 - with partition detection
1 parent aa3fb5f commit ab9d6a7

File tree

4 files changed

+125
-54
lines changed

4 files changed

+125
-54
lines changed

Uploader_GUI/RTK_Firmware_Uploader_GUI.py

Lines changed: 125 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@
1313
1414
Pyinstaller:
1515
Windows:
16-
pyinstaller --onefile --clean --noconsole --distpath=./Windows_exe --icon=RTK.ico --add-binary="RTK_Surveyor.ino.partitions.bin;." --add-binary="RTK_Surveyor.ino.bootloader.bin;." --add-binary="boot_app0.bin;." --add-binary="RTK.png;." RTK_Firmware_Uploader_GUI.py
16+
pyinstaller --onefile --clean --noconsole --distpath=./Windows_exe --icon=RTK.ico --add-binary="RTK_Surveyor_Partitions_4MB.bin;." --add-binary="RTK_Surveyor_Partitions_16MB.bin;." --add-binary="RTK_Surveyor.ino.bootloader.bin;." --add-binary="boot_app0.bin;." --add-binary="RTK.png;." RTK_Firmware_Uploader_GUI.py
1717
Linux:
18-
pyinstaller --onefile --clean --noconsole --distpath=./Linux_exe --icon=RTK.ico --add-binary="RTK_Surveyor.ino.partitions.bin:." --add-binary="RTK_Surveyor.ino.bootloader.bin:." --add-binary="boot_app0.bin:." --add-binary="RTK.png:." RTK_Firmware_Uploader_GUI.py
18+
pyinstaller --onefile --clean --noconsole --distpath=./Linux_exe --icon=RTK.ico --add-binary="RTK_Surveyor_Partitions_4MB.bin:." --add-binary="RTK_Surveyor_Partitions_16MB.bin:." --add-binary="RTK_Surveyor.ino.bootloader.bin:." --add-binary="boot_app0.bin:." --add-binary="RTK.png:." RTK_Firmware_Uploader_GUI.py
1919
2020
Pyinstaller needs:
2121
RTK_Firmware_Uploader_GUI.py (this file!)
2222
RTK.ico (icon file for the .exe)
2323
RTK.png (icon for the GUI widget)
2424
esptool.py (v3.3, copied from https://github.com/espressif/esptool/releases/tag/v3.3)
25-
RTK_Surveyor.ino.partitions.bin
25+
RTK_Surveyor_Partitions_4MB.bin
26+
RTK_Surveyor_Partitions_16MB.bin
2627
RTK_Surveyor.ino.bootloader.bin
2728
boot_app0.bin
2829
@@ -55,7 +56,7 @@
5556
# Setting constants
5657
SETTING_PORT_NAME = 'port_name'
5758
SETTING_FILE_LOCATION = 'file_location'
58-
SETTING_PARTITION_LOCATION = 'partition_location'
59+
#SETTING_PARTITION_LOCATION = 'partition_location'
5960
SETTING_BAUD_RATE = 'baud'
6061

6162
guiVersion = 'v1.3'
@@ -74,9 +75,10 @@ def resource_path(relative_path):
7475
class messageRedirect(QObject):
7576
"""Wrap a class around a QPlainTextEdit so we can redirect stdout and stderr to it"""
7677

77-
def __init__(self, edit, out=None) -> None:
78+
def __init__(self, edit, out=None, flashSize=None) -> None:
7879
self.edit = edit
7980
self.out = out
81+
self.flashSize = flashSize
8082

8183
def write(self, msg) -> None:
8284
if msg.startswith("\r"):
@@ -87,9 +89,20 @@ def write(self, msg) -> None:
8789
self.edit.insertPlainText(msg)
8890
self.edit.ensureCursorVisible()
8991
self.edit.repaint()
92+
QApplication.processEvents() # This prevents the circle of doom...
93+
9094
if self.out: # Echo to out (stdout) too if desired
9195
self.out.write(msg)
92-
QApplication.processEvents()
96+
97+
if self.flashSize:
98+
if msg.find("Detected flash size: 4MB") >= 0:
99+
self.flashSize[0] = 4
100+
elif msg.find("Detected flash size: 8MB") >= 0:
101+
self.flashSize[0] = 8
102+
elif msg.find("Detected flash size: 16MB") >= 0:
103+
self.flashSize[0] = 16
104+
elif msg.find("Detected flash size: ") >= 0:
105+
self.flashSize[0] = 0
93106

94107
def flush(self) -> None:
95108
None
@@ -105,6 +118,8 @@ class MainWidget(QWidget):
105118
def __init__(self, parent: QWidget = None) -> None:
106119
super().__init__(parent)
107120

121+
self.flashSize = [0] # flashSize needs to be mutable. Use a single element list
122+
108123
# File location line edit
109124
self.file_label = QLabel(self.tr('Firmware File:'))
110125
self.fileLocation_lineedit = QLineEdit()
@@ -117,17 +132,17 @@ def __init__(self, parent: QWidget = None) -> None:
117132
self.browse_btn.setEnabled(True)
118133
self.browse_btn.pressed.connect(self.on_browse_btn_pressed)
119134

120-
# Partition file location line edit
121-
self.partition_label = QLabel(self.tr('Partition File:'))
122-
self.partitionFileLocation_lineedit = QLineEdit()
123-
self.partition_label.setBuddy(self.partitionFileLocation_lineedit)
124-
self.partitionFileLocation_lineedit.setEnabled(False)
125-
self.partitionFileLocation_lineedit.returnPressed.connect(self.on_partition_browse_btn_pressed)
135+
# # Partition file location line edit
136+
# self.partition_label = QLabel(self.tr('Partition File:'))
137+
# self.partitionFileLocation_lineedit = QLineEdit()
138+
# self.partition_label.setBuddy(self.partitionFileLocation_lineedit)
139+
# self.partitionFileLocation_lineedit.setEnabled(False)
140+
# self.partitionFileLocation_lineedit.returnPressed.connect(self.on_partition_browse_btn_pressed)
126141

127-
# Browse for new file button
128-
self.partition_browse_btn = QPushButton(self.tr('Browse'))
129-
self.partition_browse_btn.setEnabled(True)
130-
self.partition_browse_btn.pressed.connect(self.on_partition_browse_btn_pressed)
142+
# # Browse for new file button
143+
# self.partition_browse_btn = QPushButton(self.tr('Browse'))
144+
# self.partition_browse_btn.setEnabled(True)
145+
# self.partition_browse_btn.pressed.connect(self.on_partition_browse_btn_pressed)
131146

132147
# Port Combobox
133148
self.port_label = QLabel(self.tr('COM Port:'))
@@ -167,20 +182,20 @@ def __init__(self, parent: QWidget = None) -> None:
167182
layout.addWidget(self.fileLocation_lineedit, 1, 1)
168183
layout.addWidget(self.browse_btn, 1, 2)
169184

170-
layout.addWidget(self.partition_label, 2, 0)
171-
layout.addWidget(self.partitionFileLocation_lineedit, 2, 1)
172-
layout.addWidget(self.partition_browse_btn, 2, 2)
185+
# layout.addWidget(self.partition_label, 2, 0)
186+
# layout.addWidget(self.partitionFileLocation_lineedit, 2, 1)
187+
# layout.addWidget(self.partition_browse_btn, 2, 2)
173188

174-
layout.addWidget(self.port_label, 3, 0)
175-
layout.addWidget(self.port_combobox, 3, 1)
176-
layout.addWidget(self.refresh_btn, 3, 2)
189+
layout.addWidget(self.port_label, 2, 0)
190+
layout.addWidget(self.port_combobox, 2, 1)
191+
layout.addWidget(self.refresh_btn, 2, 2)
177192

178-
layout.addWidget(self.baud_label, 4, 0)
179-
layout.addWidget(self.baud_combobox, 4, 1)
180-
layout.addWidget(self.upload_btn, 4, 2)
193+
layout.addWidget(self.baud_label, 3, 0)
194+
layout.addWidget(self.baud_combobox, 3, 1)
195+
layout.addWidget(self.upload_btn, 3, 2)
181196

182-
layout.addWidget(self.messages_label, 5, 0)
183-
layout.addWidget(self.messageBox, 6, 0, 5, 3)
197+
layout.addWidget(self.messages_label, 4, 0)
198+
layout.addWidget(self.messageBox, 5, 0, 5, 3)
184199

185200
self.setLayout(layout)
186201

@@ -208,11 +223,11 @@ def _load_settings(self) -> None:
208223
if lastFile is not None:
209224
self.fileLocation_lineedit.setText(lastFile)
210225

211-
lastFile = self.settings.value(SETTING_PARTITION_LOCATION)
212-
if lastFile is not None:
213-
self.partitionFileLocation_lineedit.setText(lastFile)
214-
else:
215-
self.partitionFileLocation_lineedit.setText(resource_path("RTK_Surveyor.ino.partitions.bin"))
226+
# lastFile = self.settings.value(SETTING_PARTITION_LOCATION)
227+
# if lastFile is not None:
228+
# self.partitionFileLocation_lineedit.setText(lastFile)
229+
# else:
230+
# self.partitionFileLocation_lineedit.setText(resource_path("RTK_Surveyor.ino.partitions.bin"))
216231

217232
baud = self.settings.value(SETTING_BAUD_RATE)
218233
if baud is not None:
@@ -224,7 +239,7 @@ def _save_settings(self) -> None:
224239
"""Save settings on shutdown."""
225240
self.settings.setValue(SETTING_PORT_NAME, self.port)
226241
self.settings.setValue(SETTING_FILE_LOCATION, self.theFileName)
227-
self.settings.setValue(SETTING_PARTITION_LOCATION, self.thePartitionFileName)
242+
# self.settings.setValue(SETTING_PARTITION_LOCATION, self.thePartitionFileName)
228243
self.settings.setValue(SETTING_BAUD_RATE, self.baudRate)
229244

230245
def _clean_settings(self) -> None:
@@ -277,10 +292,10 @@ def theFileName(self) -> str:
277292
"""Return the file name."""
278293
return self.fileLocation_lineedit.text()
279294

280-
@property
281-
def thePartitionFileName(self) -> str:
282-
"""Return the partition file name."""
283-
return self.partitionFileLocation_lineedit.text()
295+
# @property
296+
# def thePartitionFileName(self) -> str:
297+
# """Return the partition file name."""
298+
# return self.partitionFileLocation_lineedit.text()
284299

285300
def closeEvent(self, event: QCloseEvent) -> None:
286301
"""Handle Close event of the Widget."""
@@ -307,17 +322,17 @@ def on_browse_btn_pressed(self) -> None:
307322
if fileName:
308323
self.fileLocation_lineedit.setText(fileName)
309324

310-
def on_partition_browse_btn_pressed(self) -> None:
311-
"""Open dialog to select partition bin file."""
312-
options = QFileDialog.Options()
313-
fileName, _ = QFileDialog.getOpenFileName(
314-
None,
315-
"Select Partition File",
316-
"",
317-
"Parition Files (*.bin);;All Files (*)",
318-
options=options)
319-
if fileName:
320-
self.partitionFileLocation_lineedit.setText(fileName)
325+
# def on_partition_browse_btn_pressed(self) -> None:
326+
# """Open dialog to select partition bin file."""
327+
# options = QFileDialog.Options()
328+
# fileName, _ = QFileDialog.getOpenFileName(
329+
# None,
330+
# "Select Partition File",
331+
# "",
332+
# "Parition Files (*.bin);;All Files (*)",
333+
# options=options)
334+
# if fileName:
335+
# self.partitionFileLocation_lineedit.setText(fileName)
321336

322337
def on_upload_btn_pressed(self) -> None:
323338
"""Upload the firmware"""
@@ -331,7 +346,7 @@ def on_upload_btn_pressed(self) -> None:
331346

332347
fileExists = False
333348
try:
334-
f = open(self.fileLocation_lineedit.text())
349+
f = open(self.theFileName)
335350
fileExists = True
336351
except IOError:
337352
fileExists = False
@@ -341,11 +356,67 @@ def on_upload_btn_pressed(self) -> None:
341356
return
342357
f.close()
343358

359+
# fileExists = False
360+
# try:
361+
# f = open(self.thePartitionFileName)
362+
# fileExists = True
363+
# except IOError:
364+
# fileExists = False
365+
# finally:
366+
# if (fileExists == False):
367+
# self.writeMessage("File Not Found")
368+
# return
369+
# f.close()
370+
344371
try:
345372
self._save_settings() # Save the settings in case the upload crashes
346373
except:
347374
pass
348375

376+
self.flashSize[0] = 0
377+
378+
self.writeMessage("Detecting flash size\n\n")
379+
380+
command = []
381+
command.extend(["--chip","esp32"])
382+
command.extend(["--port",self.port])
383+
command.extend(["--baud",self.baudRate])
384+
command.extend(["flash_id"])
385+
386+
try:
387+
esptool.main(command)
388+
except (ValueError, IOError, FatalError, ImportError, NotImplementedInROMError, UnsupportedCommandError, NotSupportedError, RuntimeError) as err:
389+
self.writeMessage(str(err))
390+
self.messageBox.ensureCursorVisible()
391+
self.messageBox.repaint()
392+
return
393+
except:
394+
self.messageBox.ensureCursorVisible()
395+
self.messageBox.repaint()
396+
return
397+
398+
if self.flashSize[0] == 0:
399+
self.writeMessage("Flash size not detected! Defaulting to 16MB\n")
400+
self.flashSize[0] = 16
401+
else:
402+
self.writeMessage("Flash size is " + str(self.flashSize[0]) + "MB\n")
403+
404+
thePartitionFileName = ''
405+
firmwareSizeCorrect = True
406+
if self.flashSize[0] == 16:
407+
thePartitionFileName = resource_path("RTK_Surveyor_Partitions_16MB.bin")
408+
# if self.theFileName.find("16MB") < 0:
409+
# firmwareSizeCorrect = False
410+
else:
411+
thePartitionFileName = resource_path("RTK_Surveyor_Partitions_4MB.bin")
412+
# if self.theFileName.find("4MB") < 0:
413+
# firmwareSizeCorrect = False
414+
415+
if firmwareSizeCorrect == False:
416+
reply = QMessageBox.warning(self, "Firmware size mismatch", "Do you want to continue?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
417+
if reply == QMessageBox.No:
418+
return
419+
349420
self.writeMessage("Uploading firmware\n")
350421

351422
command = []
@@ -355,7 +426,7 @@ def on_upload_btn_pressed(self) -> None:
355426
command.extend(["--baud",self.baudRate])
356427
command.extend(["--before","default_reset","--after","hard_reset","write_flash","-z","--flash_mode","dio","--flash_freq","80m","--flash_size","detect"])
357428
command.extend(["0x1000",resource_path("RTK_Surveyor.ino.bootloader.bin")])
358-
command.extend(["0x8000",self.thePartitionFileName])
429+
command.extend(["0x8000",thePartitionFileName])
359430
command.extend(["0xe000",resource_path("boot_app0.bin")])
360431
command.extend(["0x10000",self.theFileName])
361432

@@ -380,11 +451,11 @@ def on_upload_btn_pressed(self) -> None:
380451
app.setApplicationName('SparkFun RTK Firmware Uploader ' + guiVersion)
381452
app.setWindowIcon(QIcon(resource_path("RTK.png")))
382453
w = MainWidget()
383-
if 0: # Change to 0 to have the messages echoed on stdout
384-
sys.stdout = messageRedirect(w.messageBox) # Divert stdout to messageBox
454+
if 1: # Change to 0 to have the messages echoed on stdout
455+
sys.stdout = messageRedirect(w.messageBox, flashSize=w.flashSize) # Divert stdout to messageBox. Report flash size via flashSize
385456
sys.stderr = messageRedirect(w.messageBox) # Divert stderr to messageBox
386457
else:
387-
sys.stdout = messageRedirect(w.messageBox, sys.stdout) # Echo to stdout too
388-
sys.stderr = messageRedirect(w.messageBox, sys.stderr) # Echo to stderr too
458+
sys.stdout = messageRedirect(w.messageBox, flashSize=w.flashSize, out=sys.stdout) # Echo to stdout too
459+
sys.stderr = messageRedirect(w.messageBox, out=sys.stderr) # Echo to stderr too
389460
w.show()
390461
sys.exit(app.exec_())
3 KB
Binary file not shown.
-173 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)