1010# import action things - the .syntax is used since these are part of the package
1111from .au_worker import AUxWorker
1212from .au_action import AxJob
13- from .au_act_esptool import AUxEsptoolDetectFlash , AUxEsptoolUploadFirmware , AUxEsptoolResetESP32
13+ from .au_act_esptool import AUxEsptoolDetectFlash , AUxEsptoolUploadFirmware , AUxEsptoolResetESP32 , \
14+ AUxEsptoolEraseFlash , AUxEsptoolReadMAC
1415
1516import darkdetect
1617import sys
@@ -116,10 +117,33 @@ class MainWidget(QWidget):
116117 sig_message = pyqtSignal (str )
117118 sig_finished = pyqtSignal (int , str , int )
118119
120+ def _createMenuBar (self ):
121+ self .menuBar = QMenuBar (self )
122+
123+ self .extrasReadMACAction = QAction ("Read WiFi MAC" , self )
124+ self .extrasResetAction = QAction ("Reset ESP32" , self )
125+ self .extrasEraseAction = QAction ("Erase Flash" , self )
126+
127+ extrasMenu = self .menuBar .addMenu ("Extras" )
128+ extrasMenu .addAction (self .extrasReadMACAction )
129+ extrasMenu .addAction (self .extrasResetAction )
130+ extrasMenu .addAction (self .extrasEraseAction )
131+
132+ self .extrasReadMACAction .triggered .connect (self .readMAC )
133+ self .extrasResetAction .triggered .connect (self .tera_term_reset )
134+ self .extrasEraseAction .triggered .connect (self .eraseChip )
135+
136+ self .extrasReadMACAction .setDisabled (False )
137+ self .extrasResetAction .setDisabled (False )
138+ self .extrasEraseAction .setDisabled (False )
139+
119140 def __init__ (self , parent : QWidget = None ) -> None :
120141 super ().__init__ (parent )
121142
122143 self .flashSize = 0
144+ self .macAddress = "UNKNOWN"
145+
146+ self ._createMenuBar ()
123147
124148 # File location line edit
125149 self .file_label = QLabel (self .tr ('Firmware File:' ))
@@ -152,10 +176,6 @@ def __init__(self, parent: QWidget = None) -> None:
152176 self .update_com_ports ()
153177 self .port_combobox .popupAboutToBeShown .connect (self .on_port_combobox )
154178
155- # Reset Button
156- self .reset_btn = QPushButton (self .tr ('Reset ESP32' ))
157- self .reset_btn .clicked .connect (self .tera_term_reset )
158-
159179 # Baudrate Combobox
160180 self .baud_label = QLabel (self .tr ('Baud Rate:' ))
161181 self .baud_combobox = QComboBox ()
@@ -181,25 +201,26 @@ def __init__(self, parent: QWidget = None) -> None:
181201
182202 # Arrange Layout
183203 layout = QGridLayout ()
184-
185- layout .addWidget (self .file_label , 1 , 0 )
186- layout .addWidget (self .fileLocation_lineedit , 1 , 1 )
187- layout .addWidget (self .browse_btn , 1 , 2 )
188204
189- # layout.addWidget(self.partition_label, 2, 0)
190- # layout.addWidget(self.partitionFileLocation_lineedit, 2, 1)
191- # layout.addWidget(self.partition_browse_btn, 2, 2)
205+ layout .addWidget (self .menuBar , 1 , 0 )
206+
207+ layout .addWidget (self .file_label , 2 , 0 )
208+ layout .addWidget (self .fileLocation_lineedit , 2 , 1 )
209+ layout .addWidget (self .browse_btn , 2 , 2 )
210+
211+ # layout.addWidget(self.partition_label, 3, 0)
212+ # layout.addWidget(self.partitionFileLocation_lineedit, 3, 1)
213+ # layout.addWidget(self.partition_browse_btn, 3, 2)
192214
193- layout .addWidget (self .port_label , 2 , 0 )
194- layout .addWidget (self .port_combobox , 2 , 1 )
195- layout .addWidget (self .reset_btn , 2 , 2 )
215+ layout .addWidget (self .port_label , 3 , 0 )
216+ layout .addWidget (self .port_combobox , 3 , 1 )
196217
197- layout .addWidget (self .baud_label , 3 , 0 )
198- layout .addWidget (self .baud_combobox , 3 , 1 )
199- layout .addWidget (self .upload_btn , 3 , 2 )
218+ layout .addWidget (self .baud_label , 4 , 0 )
219+ layout .addWidget (self .baud_combobox , 4 , 1 )
220+ layout .addWidget (self .upload_btn , 4 , 2 )
200221
201- layout .addWidget (self .messages_label , 4 , 0 )
202- layout .addWidget (self .messageBox , 5 , 0 , 5 , 3 )
222+ layout .addWidget (self .messages_label , 5 , 0 )
223+ layout .addWidget (self .messageBox , 6 , 0 , 6 , 3 )
203224
204225 self .setLayout (layout )
205226
@@ -222,7 +243,8 @@ def __init__(self, parent: QWidget = None) -> None:
222243
223244 # add the actions/commands for this app to the background processing thread.
224245 # These actions are passed jobs to execute.
225- self ._worker .add_action (AUxEsptoolDetectFlash (), AUxEsptoolUploadFirmware (), AUxEsptoolResetESP32 ())
246+ self ._worker .add_action (AUxEsptoolDetectFlash (), AUxEsptoolUploadFirmware (), AUxEsptoolResetESP32 (), \
247+ AUxEsptoolEraseFlash (), AUxEsptoolReadMAC ())
226248
227249 #--------------------------------------------------------------
228250 # callback function for the background worker.
@@ -269,6 +291,10 @@ def appendMessage(self, msg: str) -> None:
269291 elif msg .find ("Detected flash size: " ) >= 0 :
270292 self .flashSize = 0
271293
294+ macAddrPtr = msg .find ("MAC: " )
295+ if macAddrPtr >= 0 :
296+ self .macAddress = msg [macAddrPtr + len ("MAC: " ):]
297+
272298 @pyqtSlot (str )
273299 def writeMessage (self , msg : str ) -> None :
274300 self .messageBox .moveCursor (QTextCursor .End )
@@ -287,18 +313,29 @@ def writeMessage(self, msg: str) -> None:
287313 @pyqtSlot (int , str , int )
288314 def on_finished (self , status , action_type , job_id ) -> None :
289315
316+ # If the Read MAC is finished, re-enable the UX
317+ if action_type == AUxEsptoolReadMAC .ACTION_ID :
318+ self .writeMessage ("Read MAC complete..." )
319+ self .writeMessage ("WiFi MAC Address is {}" .format (self .macAddress ))
320+ self .disable_interface (False )
321+
322+ # If the flash erase is finished, re-enable the UX
323+ if action_type == AUxEsptoolEraseFlash .ACTION_ID :
324+ self .writeMessage ("Flash erase complete..." )
325+ self .disable_interface (False )
326+
290327 # If the flash detection is finished, trigger the upload
291328 if action_type == AUxEsptoolDetectFlash .ACTION_ID :
292329 self .writeMessage ("Flash detection complete. Uploading firmware..." )
293330 self .do_upload ()
294331
295332 # If the upload is finished, trigger a reset
296- elif action_type == AUxEsptoolUploadFirmware .ACTION_ID :
333+ if action_type == AUxEsptoolUploadFirmware .ACTION_ID :
297334 self .writeMessage ("Firmware upload complete. Resetting ESP32..." )
298335 self .esptool_reset ()
299336
300- # re-enable the UX
301- else :
337+ # If the reset is finished, re-enable the UX
338+ if action_type == AUxEsptoolResetESP32 . ACTION_ID :
302339 self .writeMessage ("Reset complete..." )
303340 self .disable_interface (False )
304341
@@ -375,8 +412,7 @@ def update_baud_rates(self) -> None:
375412 # Highest speed first so code defaults to that
376413 # if settings.value(SETTING_BAUD_RATE) is None
377414 self .baud_combobox .clear ()
378- if (platform .system () != "Darwin" ): # 921600 fails on MacOS
379- self .baud_combobox .addItem ("921600" , 921600 )
415+ self .baud_combobox .addItem ("921600" , 921600 )
380416 self .baud_combobox .addItem ("460800" , 460800 )
381417 self .baud_combobox .addItem ("115200" , 115200 )
382418
@@ -444,7 +480,77 @@ def on_browse_btn_pressed(self) -> None:
444480 def disable_interface (self , bDisable = False ):
445481
446482 self .upload_btn .setDisabled (bDisable )
447- self .reset_btn .setDisabled (bDisable )
483+ self .extrasEraseAction .setDisabled (bDisable )
484+ self .extrasReadMACAction .setDisabled (bDisable )
485+ self .extrasResetAction .setDisabled (bDisable )
486+
487+ def eraseChip (self ) -> None :
488+ """Perform erase_flash"""
489+ portAvailable = False
490+ for desc , name , sys in gen_serial_ports ():
491+ if (sys == self .port ):
492+ portAvailable = True
493+ if (portAvailable == False ):
494+ self .writeMessage ("Port No Longer Available" )
495+ return
496+
497+ try :
498+ self ._save_settings () # Save the settings in case the command fails
499+ except :
500+ pass
501+
502+ self .writeMessage ("Erasing flash\n \n " )
503+
504+ command = []
505+ command .extend (["--chip" ,"esp32" ])
506+ command .extend (["--port" ,self .port ])
507+ command .extend (["--before" ,"default_reset" ])
508+ command .extend (["erase_flash" ])
509+
510+ # Create a job and add it to the job queue. The worker thread will pick this up and
511+ # process the job. Can set job values using dictionary syntax, or attribute assignments
512+ #
513+ # Note - the job is defined with the ID of the target action
514+ theJob = AxJob (AUxEsptoolEraseFlash .ACTION_ID , {"command" :command })
515+
516+ # Send the job to the worker to process
517+ self ._worker .add_job (theJob )
518+
519+ self .disable_interface (True )
520+
521+ def readMAC (self ) -> None :
522+ """Perform read_mac"""
523+ portAvailable = False
524+ for desc , name , sys in gen_serial_ports ():
525+ if (sys == self .port ):
526+ portAvailable = True
527+ if (portAvailable == False ):
528+ self .writeMessage ("Port No Longer Available" )
529+ return
530+
531+ try :
532+ self ._save_settings () # Save the settings in case the command fails
533+ except :
534+ pass
535+
536+ self .writeMessage ("Reading WiFi MAC address\n \n " )
537+
538+ command = []
539+ command .extend (["--chip" ,"esp32" ])
540+ command .extend (["--port" ,self .port ])
541+ command .extend (["--before" ,"default_reset" ])
542+ command .extend (["read_mac" ])
543+
544+ # Create a job and add it to the job queue. The worker thread will pick this up and
545+ # process the job. Can set job values using dictionary syntax, or attribute assignments
546+ #
547+ # Note - the job is defined with the ID of the target action
548+ theJob = AxJob (AUxEsptoolReadMAC .ACTION_ID , {"command" :command })
549+
550+ # Send the job to the worker to process
551+ self ._worker .add_job (theJob )
552+
553+ self .disable_interface (True )
448554
449555 def on_upload_btn_pressed (self ) -> None :
450556 """Get ready to upload the firmware. First, detect the flash size"""
@@ -468,7 +574,6 @@ def on_upload_btn_pressed(self) -> None:
468574 command = []
469575 command .extend (["--chip" ,"esp32" ])
470576 command .extend (["--port" ,self .port ])
471- command .extend (["--baud" ,self .baudRate ])
472577 command .extend (["--before" ,"default_reset" ,"--after" ,"no_reset" ])
473578 command .extend (["flash_id" ])
474579
@@ -550,11 +655,20 @@ def do_upload(self) -> None:
550655 sleep (1.0 );
551656 self .writeMessage ("Uploading firmware\n " )
552657
658+ baud = self .baudRate
659+ if baud == "921600" :
660+ if (platform .system () == "Darwin" ): # 921600 fails on MacOS
661+ self .writeMessage ("MacOS detected. Limiting baud to 460800\n " )
662+ baud = "460800"
663+ if (str (self .port_combobox .currentText ()).find ("CH342" ) >= 0 ): # 921600 fails on CH342
664+ self .writeMessage ("CH342 detected. Limiting baud to 460800\n " )
665+ baud = "460800"
666+
553667 command = []
554668 #command.extend(["--trace"]) # Useful for debugging
555669 command .extend (["--chip" ,"esp32" ])
556670 command .extend (["--port" ,self .port ])
557- command .extend (["--baud" ,self . baudRate ])
671+ command .extend (["--baud" ,baud ])
558672 command .extend (["--before" ,"default_reset" ,"--after" ,"no_reset" ,"write_flash" ,"-z" ,"--flash_mode" ,"dio" ,"--flash_freq" ,"80m" ,"--flash_size" ,"detect" ])
559673 command .extend (["0x1000" ,resource_path ("RTK_Surveyor.ino.bootloader.bin" )])
560674 command .extend (["0x8000" ,thePartitionFileName ])
0 commit comments