13
13
14
14
Pyinstaller:
15
15
Windows:
16
- pyinstaller --onefile --clean --noconsole --distpath=./Windows_exe --icon=RTK.ico --add-data="esptool.py;." --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.ino.partitions.bin;." --add-binary="RTK_Surveyor.ino.bootloader.bin;." --add-binary="boot_app0.bin;." --add-binary="RTK.png;." RTK_Firmware_Uploader_GUI.py
17
17
Linux:
18
- pyinstaller --onefile --clean --noconsole --distpath=./Linux_exe --icon=RTK.ico --add-data="esptool.py:." --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.ino.partitions.bin:." --add-binary="RTK_Surveyor.ino.bootloader.bin:." --add-binary="boot_app0.bin:." --add-binary="RTK.png:." RTK_Firmware_Uploader_GUI.py
19
19
20
20
Pyinstaller needs:
21
21
RTK_Firmware_Uploader_GUI.py (this file!)
@@ -68,6 +68,30 @@ def resource_path(relative_path):
68
68
base_path = getattr (sys , '_MEIPASS' , os .path .dirname (os .path .abspath (__file__ )))
69
69
return os .path .join (base_path , relative_path )
70
70
71
+ class messageRedirect :
72
+ """Wrap a class around a QPlainTextEdit so we can redirect stdout and stderr to it"""
73
+
74
+ def __init__ (self , edit , out = None ) -> None :
75
+ self .edit = edit
76
+ self .out = out
77
+ self .edit .setReadOnly (True )
78
+ self .edit .clear ()
79
+
80
+ def write (self , msg ) -> None :
81
+ if msg .startswith ("\r " ):
82
+ self .edit .moveCursor (QTextCursor .StartOfLine , QTextCursor .KeepAnchor )
83
+ self .edit .cut ()
84
+ self .edit .insertPlainText (msg [1 :])
85
+ else :
86
+ self .edit .insertPlainText (msg )
87
+ self .edit .ensureCursorVisible ()
88
+ self .edit .repaint ()
89
+ if self .out : # Echo to out (stdout) too if desired
90
+ self .out .write (msg )
91
+
92
+ def flush (self ) -> None :
93
+ None
94
+
71
95
# noinspection PyArgumentList
72
96
73
97
class MainWidget (QWidget ):
@@ -76,8 +100,6 @@ class MainWidget(QWidget):
76
100
def __init__ (self , parent : QWidget = None ) -> None :
77
101
super ().__init__ (parent )
78
102
79
- self .p = None # This will be the esptool QProcess
80
-
81
103
# File location line edit
82
104
self .msg_label = QLabel (self .tr ('Firmware File:' ))
83
105
self .fileLocation_lineedit = QLineEdit ()
@@ -118,7 +140,7 @@ def __init__(self, parent: QWidget = None) -> None:
118
140
self .messages_label = QLabel (self .tr ('Status / Warnings:' ))
119
141
120
142
# Messages Window
121
- self .messages = QPlainTextEdit ()
143
+ self .messageBox = QPlainTextEdit ()
122
144
123
145
# Arrange Layout
124
146
layout = QGridLayout ()
@@ -136,33 +158,20 @@ def __init__(self, parent: QWidget = None) -> None:
136
158
layout .addWidget (self .upload_btn , 3 , 2 )
137
159
138
160
layout .addWidget (self .messages_label , 4 , 0 )
139
- layout .addWidget (self .messages , 5 , 0 , 5 , 3 )
161
+ layout .addWidget (self .messageBox , 5 , 0 , 5 , 3 )
140
162
141
163
self .setLayout (layout )
142
164
143
165
#self._clean_settings() # This will delete all existing settings! Use with caution!
144
166
145
167
self ._load_settings ()
146
168
147
- # Make the text edit window read-only
148
- self .messages .setReadOnly (True )
149
- self .messages .clear () # Clear the message window
150
-
151
- def addMessage (self , msg : str ) -> None :
152
- """Add msg to the messages window, ensuring that it is visible"""
153
- self .messages .moveCursor (QTextCursor .End )
154
- self .messages .ensureCursorVisible ()
155
- self .messages .appendPlainText (msg )
156
- self .messages .ensureCursorVisible ()
157
- self .repaint () # Update/refresh the message window
158
-
159
- def insertMessageText (self , msg : str ) -> None :
160
- """Add msg to the messages window, ensuring that it is visible"""
161
- self .messages .moveCursor (QTextCursor .End )
162
- self .messages .ensureCursorVisible ()
163
- self .messages .insertPlainText (msg )
164
- self .messages .ensureCursorVisible ()
165
- self .repaint () # Update/refresh the message window
169
+ def writeMessage (self , msg ) -> None :
170
+ self .messageBox .moveCursor (QTextCursor .End )
171
+ self .messageBox .ensureCursorVisible ()
172
+ self .messageBox .appendPlainText (msg )
173
+ self .messageBox .ensureCursorVisible ()
174
+ self .messageBox .repaint ()
166
175
167
176
def _load_settings (self ) -> None :
168
177
"""Load settings on startup."""
@@ -253,7 +262,7 @@ def closeEvent(self, event: QCloseEvent) -> None:
253
262
254
263
def on_refresh_btn_pressed (self ) -> None :
255
264
self .update_com_ports ()
256
- self .addMessage ("Ports Refreshed\n " )
265
+ self .writeMessage ("Ports Refreshed\n " )
257
266
258
267
def on_browse_btn_pressed (self ) -> None :
259
268
"""Open dialog to select bin file."""
@@ -267,37 +276,14 @@ def on_browse_btn_pressed(self) -> None:
267
276
if fileName :
268
277
self .fileLocation_lineedit .setText (fileName )
269
278
270
- def handle_stderr (self ) -> None :
271
- data = self .p .readAllStandardError ()
272
- stderr = bytes (data ).decode ("utf8" )
273
- self .insertMessageText (stderr )
274
-
275
- def handle_stdout (self ) -> None :
276
- data = self .p .readAllStandardOutput ()
277
- stdout = bytes (data ).decode ("utf8" )
278
- self .insertMessageText (stdout )
279
-
280
- def handle_state (self , state ) -> None :
281
- states = {
282
- QProcess .NotRunning : 'Not running\n ' ,
283
- QProcess .Starting : 'Starting\n ' ,
284
- QProcess .Running : 'Running\n ' ,
285
- }
286
- state_name = states [state ]
287
- self .addMessage (f"Upload state changed: { state_name } " )
288
-
289
- def process_finished (self ) -> None :
290
- self .addMessage ("Upload finished\n " )
291
- self .p = None
292
-
293
279
def on_upload_btn_pressed (self ) -> None :
294
280
"""Upload the firmware"""
295
281
portAvailable = False
296
282
for desc , name , sys in gen_serial_ports ():
297
283
if (sys == self .port ):
298
284
portAvailable = True
299
285
if (portAvailable == False ):
300
- self .addMessage ("Port No Longer Available" )
286
+ self .writeMessage ("Port No Longer Available" )
301
287
return
302
288
303
289
fileExists = False
@@ -308,37 +294,25 @@ def on_upload_btn_pressed(self) -> None:
308
294
fileExists = False
309
295
finally :
310
296
if (fileExists == False ):
311
- self .addMessage ("File Not Found" )
297
+ self .writeMessage ("File Not Found" )
312
298
return
313
299
f .close ()
314
300
315
- if self .p is None :
316
- self .addMessage ("Uploading firmware\n " )
317
-
318
- self .p = QProcess ()
319
- self .p .readyReadStandardOutput .connect (self .handle_stdout )
320
- self .p .readyReadStandardError .connect (self .handle_stderr )
321
- self .p .stateChanged .connect (self .handle_state )
322
- self .p .finished .connect (self .process_finished )
323
-
324
- command = []
325
- command .append (resource_path ("esptool.py" ))
326
- command .extend (["--chip" ,"esp32" ])
327
- command .extend (["--port" ,self .port ])
328
- command .extend (["--baud" ,self .baudRate ])
329
- command .extend (["--before" ,"default_reset" ,"--after" ,"hard_reset" ,"write_flash" ,"-z" ,"--flash_mode" ,"dio" ,"--flash_freq" ,"80m" ,"--flash_size" ,"detect" ])
330
- command .extend (["0x1000" ,resource_path ("RTK_Surveyor.ino.bootloader.bin" )])
331
- command .extend (["0x8000" ,resource_path ("RTK_Surveyor.ino.partitions.bin" )])
332
- command .extend (["0xe000" ,resource_path ("boot_app0.bin" )])
333
- command .extend (["0x10000" ,self .theFileName ])
301
+ self .writeMessage ("Uploading firmware\n " )
334
302
335
- self .addMessage ("Command: python %s\n " % " " .join (command ))
303
+ command = []
304
+ command .extend (["--chip" ,"esp32" ])
305
+ command .extend (["--port" ,self .port ])
306
+ command .extend (["--baud" ,self .baudRate ])
307
+ command .extend (["--before" ,"default_reset" ,"--after" ,"hard_reset" ,"write_flash" ,"-z" ,"--flash_mode" ,"dio" ,"--flash_freq" ,"80m" ,"--flash_size" ,"detect" ])
308
+ command .extend (["0x1000" ,resource_path ("RTK_Surveyor.ino.bootloader.bin" )])
309
+ command .extend (["0x8000" ,resource_path ("RTK_Surveyor.ino.partitions.bin" )])
310
+ command .extend (["0xe000" ,resource_path ("boot_app0.bin" )])
311
+ command .extend (["0x10000" ,self .theFileName ])
336
312
337
- self . p . start ( 'python' , command )
313
+ self . writeMessage ( "Command: esptool.main(%s) \n \n " % " " . join ( command ) )
338
314
339
- else :
340
- self .addMessage ("\n Uploader is already running!\n " )
341
-
315
+ esptool .main (command )
342
316
343
317
if __name__ == '__main__' :
344
318
from sys import exit as sysExit
@@ -347,5 +321,11 @@ def on_upload_btn_pressed(self) -> None:
347
321
app .setApplicationName ('SparkFun RTK Firmware Uploader ' + guiVersion )
348
322
app .setWindowIcon (QIcon (resource_path ("RTK.png" )))
349
323
w = MainWidget ()
324
+ if 1 :
325
+ sys .stdout = messageRedirect (w .messageBox ) # Divert stdout to messageBox
326
+ sys .stderr = messageRedirect (w .messageBox ) # Divert stderr to messageBox
327
+ else :
328
+ sys .stdout = messageRedirect (w .messageBox , sys .stdout ) # Echo to stdout too
329
+ sys .stderr = messageRedirect (w .messageBox , sys .stderr ) # Echo to stderr too
350
330
w .show ()
351
331
sys .exit (app .exec_ ())
0 commit comments