1 # -*- coding: utf-8 -*- |
1 # -*- coding: utf-8 -*- |
2 |
2 |
3 # Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
3 # Copyright (c) 2019 - 2020 Detlev Offenbach <detlev@die-offenbachs.de> |
4 # |
4 # |
5 |
5 |
6 """ |
6 """ |
7 Module implementing some utility functions and the MicroPythonDevice base |
7 Module implementing some utility functions and the MicroPythonDevice base |
8 class. |
8 class. |
9 """ |
9 """ |
10 |
10 |
11 |
11 |
12 import sys |
12 import sys |
13 |
13 |
14 from PyQt5.QtCore import pyqtSlot |
14 from PyQt5.QtCore import pyqtSlot, QProcess |
15 from PyQt5.QtWidgets import QDialog |
15 from PyQt5.QtWidgets import QDialog |
16 |
16 |
17 from E5Gui import E5MessageBox |
17 from E5Gui import E5MessageBox |
18 from E5Gui.E5ProcessDialog import E5ProcessDialog |
18 from E5Gui.E5ProcessDialog import E5ProcessDialog |
19 from E5Gui.E5Application import e5App |
19 from E5Gui.E5Application import e5App |
21 from .MicroPythonDevices import MicroPythonDevice |
21 from .MicroPythonDevices import MicroPythonDevice |
22 from .MicroPythonWidget import HAS_QTCHART |
22 from .MicroPythonWidget import HAS_QTCHART |
23 |
23 |
24 import Preferences |
24 import Preferences |
25 |
25 |
26 |
|
27 # TODO: add backupFlash: python ./esptool.py --port /dev/ttyUSB4 --baud 115200 read_flash 0x00000 0x400000 backup.img |
|
28 # selection of sizes: 1MB, 2MB, 4MB, 8MB, 16M (0x100000, 0x200000, 0x400000, 0x800000, 0x1000000) |
|
29 # ESP8266: 256KB, 512KB (0x40000, 0x80000) |
|
30 # TODO: add restoreFlash: python esptool.py --port /dev/ttyUSB4 write_flash --flash_mode qio 0x00000 backup.img |
|
31 # alternative modes for --flash_mode: qio,qout,dio,dout |
|
32 # optional: --flash_size 1MB, 2MB, 4MB, 8MB, 16M (ESP8266 zusätzlich 256KB, 512KB) |
|
33 # TODO: add showChipID: python esptool.py --port /dev/ttyUSB4 --baud 115200 chip_id |
|
34 # TODO: add showFlashID: python esptool.py --port /dev/ttyUSB4 --baud 115200 flash_id |
|
35 # TODO: add readMAC: python esptool.py --port /dev/ttyUSB4 --baud 115200 read_mac |
|
36 |
26 |
37 class EspDevice(MicroPythonDevice): |
27 class EspDevice(MicroPythonDevice): |
38 """ |
28 """ |
39 Class implementing the device for ESP32 and ESP8266 based boards. |
29 Class implementing the device for ESP32 and ESP8266 based boards. |
40 """ |
30 """ |
142 self.__flashMicroPython) |
132 self.__flashMicroPython) |
143 act.setEnabled(not connected) |
133 act.setEnabled(not connected) |
144 menu.addSeparator() |
134 menu.addSeparator() |
145 act = menu.addAction(self.tr("Flash Additional Firmware"), |
135 act = menu.addAction(self.tr("Flash Additional Firmware"), |
146 self.__flashAddons) |
136 self.__flashAddons) |
|
137 act.setEnabled(not connected) |
|
138 menu.addSeparator() |
|
139 act = menu.addAction(self.tr("Backup Firmware"), |
|
140 self.__backupFlash) |
|
141 act.setEnabled(not connected) |
|
142 act = menu.addAction(self.tr("Restore Firmware"), |
|
143 self.__restoreFlash) |
|
144 act.setEnabled(not connected) |
|
145 menu.addSeparator() |
|
146 act = menu.addAction(self.tr("Show Chip ID"), |
|
147 self.__showChipID) |
|
148 act.setEnabled(not connected) |
|
149 act = menu.addAction(self.tr("Show Flash ID"), |
|
150 self.__showFlashID) |
|
151 act.setEnabled(not connected) |
|
152 act = menu.addAction(self.tr("Show MAC Address"), |
|
153 self.__showMACAddress) |
147 act.setEnabled(not connected) |
154 act.setEnabled(not connected) |
148 menu.addSeparator() |
155 menu.addSeparator() |
149 act = menu.addAction(self.tr("Reset Device"), self.__resetDevice) |
156 act = menu.addAction(self.tr("Reset Device"), self.__resetDevice) |
150 menu.addSeparator() |
157 menu.addSeparator() |
151 menu.addAction(self.tr("Install 'esptool.py'"), self.__installEspTool) |
158 menu.addAction(self.tr("Install 'esptool.py'"), self.__installEspTool) |
223 "write_flash", |
232 "write_flash", |
224 flashAddress.lower(), |
233 flashAddress.lower(), |
225 firmware, |
234 firmware, |
226 ] |
235 ] |
227 dlg = E5ProcessDialog(self.tr("'esptool write_flash' Output"), |
236 dlg = E5ProcessDialog(self.tr("'esptool write_flash' Output"), |
228 self.tr("Flash Additional Firmware")) |
237 self.tr("Flash Additional Firmware"), |
|
238 showProgress=True) |
229 res = dlg.startProcess(sys.executable, flashArgs) |
239 res = dlg.startProcess(sys.executable, flashArgs) |
230 if res: |
240 if res: |
231 dlg.exec_() |
241 dlg.exec_() |
232 |
242 |
233 @pyqtSlot() |
243 @pyqtSlot() |
|
244 def __backupFlash(self): |
|
245 """ |
|
246 Private slot to backup the currently flashed firmware. |
|
247 """ |
|
248 from .EspBackupRestoreFirmwareDialog import ( |
|
249 EspBackupRestoreFirmwareDialog |
|
250 ) |
|
251 dlg = EspBackupRestoreFirmwareDialog(backupMode=True) |
|
252 if dlg.exec_() == QDialog.Accepted: |
|
253 chip, flashSize, flashMode, firmware = dlg.getData() |
|
254 flashArgs = [ |
|
255 "-u", |
|
256 "-m", "esptool", |
|
257 "--chip", chip, |
|
258 "--port", self.microPython.getCurrentPort(), |
|
259 "read_flash", |
|
260 "0x0", flashSize, |
|
261 firmware, |
|
262 ] |
|
263 dlg = E5ProcessDialog(self.tr("'esptool read_flash' Output"), |
|
264 self.tr("Backup Firmware"), |
|
265 showProgress=True) |
|
266 res = dlg.startProcess(sys.executable, flashArgs) |
|
267 if res: |
|
268 dlg.exec_() |
|
269 |
|
270 @pyqtSlot() |
|
271 def __restoreFlash(self): |
|
272 """ |
|
273 Private slot to restore a previously saved firmware. |
|
274 """ |
|
275 from .EspBackupRestoreFirmwareDialog import ( |
|
276 EspBackupRestoreFirmwareDialog |
|
277 ) |
|
278 dlg = EspBackupRestoreFirmwareDialog(backupMode=False) |
|
279 if dlg.exec_() == QDialog.Accepted: |
|
280 chip, flashSize, flashMode, firmware = dlg.getData() |
|
281 flashArgs = [ |
|
282 "-u", |
|
283 "-m", "esptool", |
|
284 "--chip", chip, |
|
285 "--port", self.microPython.getCurrentPort(), |
|
286 "write_flash", |
|
287 "--flash_mode", flashMode, |
|
288 ] |
|
289 if bool(flashSize): |
|
290 flashArgs.extend([ |
|
291 "--flash_size", flashSize, |
|
292 ]) |
|
293 flashArgs.extend([ |
|
294 "0x0", |
|
295 firmware, |
|
296 ]) |
|
297 dlg = E5ProcessDialog(self.tr("'esptool write_flash' Output"), |
|
298 self.tr("Restore Firmware"), |
|
299 showProgress=True) |
|
300 res = dlg.startProcess(sys.executable, flashArgs) |
|
301 if res: |
|
302 dlg.exec_() |
|
303 |
|
304 @pyqtSlot() |
|
305 def __showChipID(self): |
|
306 """ |
|
307 Private slot to show the ID of the ESP chip. |
|
308 """ |
|
309 args = [ |
|
310 "-u", |
|
311 "-m", "esptool", |
|
312 "--port", self.microPython.getCurrentPort(), |
|
313 "chip_id" |
|
314 ] |
|
315 dlg = E5ProcessDialog(self.tr("'esptool chip_id' Output"), |
|
316 self.tr("Show Chip ID")) |
|
317 res = dlg.startProcess(sys.executable, args) |
|
318 if res: |
|
319 dlg.exec_() |
|
320 |
|
321 @pyqtSlot() |
|
322 def __showFlashID(self): |
|
323 """ |
|
324 Private slot to show the ID of the ESP flash chip. |
|
325 """ |
|
326 args = [ |
|
327 "-u", |
|
328 "-m", "esptool", |
|
329 "--port", self.microPython.getCurrentPort(), |
|
330 "flash_id" |
|
331 ] |
|
332 dlg = E5ProcessDialog(self.tr("'esptool flash_id' Output"), |
|
333 self.tr("Show Flash ID")) |
|
334 res = dlg.startProcess(sys.executable, args) |
|
335 if res: |
|
336 dlg.exec_() |
|
337 |
|
338 @pyqtSlot() |
|
339 def __showMACAddress(self): |
|
340 """ |
|
341 Private slot to show the MAC address of the ESP chip. |
|
342 """ |
|
343 args = [ |
|
344 "-u", |
|
345 "-m", "esptool", |
|
346 "--port", self.microPython.getCurrentPort(), |
|
347 "read_mac" |
|
348 ] |
|
349 dlg = E5ProcessDialog(self.tr("'esptool read_mac' Output"), |
|
350 self.tr("Show MAC Address")) |
|
351 res = dlg.startProcess(sys.executable, args) |
|
352 if res: |
|
353 dlg.exec_() |
|
354 |
|
355 @pyqtSlot() |
234 def __resetDevice(self): |
356 def __resetDevice(self): |
235 """ |
357 """ |
236 Private slot to reset the connected device. |
358 Private slot to reset the connected device. |
237 """ |
359 """ |
238 self.microPython.commandsInterface().execute([ |
360 if self.microPython.isConnected(): |
239 "import machine", |
361 self.microPython.commandsInterface().execute([ |
240 "machine.reset()", |
362 "import machine", |
241 ]) |
363 "machine.reset()", |
|
364 ]) |
|
365 else: |
|
366 # perform a reset via esptool using flash_id command ignoring |
|
367 # the output |
|
368 args = [ |
|
369 "-u", |
|
370 "-m", "esptool", |
|
371 "--port", self.microPython.getCurrentPort(), |
|
372 "flash_id" |
|
373 ] |
|
374 proc = QProcess() |
|
375 proc.start(sys.executable, args) |
|
376 procStarted = proc.waitForStarted(10000) |
|
377 if procStarted: |
|
378 proc.waitForFinished(10000) |
242 |
379 |
243 @pyqtSlot() |
380 @pyqtSlot() |
244 def __installEspTool(self): |
381 def __installEspTool(self): |
245 """ |
382 """ |
246 Private slot to install the esptool package via pip. |
383 Private slot to install the esptool package via pip. |