6 """ |
6 """ |
7 Module implementing the device interface class for ESP32 and ESP8266 based |
7 Module implementing the device interface class for ESP32 and ESP8266 based |
8 boards. |
8 boards. |
9 """ |
9 """ |
10 |
10 |
11 from PyQt6.QtCore import QProcess, pyqtSlot |
11 from PyQt6.QtCore import QProcess, QUrl, pyqtSlot |
|
12 from PyQt6.QtNetwork import QNetworkRequest |
12 from PyQt6.QtWidgets import QDialog |
13 from PyQt6.QtWidgets import QDialog |
13 |
14 |
14 from eric7 import Preferences |
15 from eric7 import Globals, Preferences |
15 from eric7.EricWidgets import EricMessageBox |
16 from eric7.EricWidgets import EricMessageBox |
16 from eric7.EricWidgets.EricApplication import ericApp |
17 from eric7.EricWidgets.EricApplication import ericApp |
17 from eric7.EricWidgets.EricProcessDialog import EricProcessDialog |
18 from eric7.EricWidgets.EricProcessDialog import EricProcessDialog |
18 from eric7.SystemUtilities import PythonUtilities |
19 from eric7.SystemUtilities import PythonUtilities |
19 |
20 |
20 from .MicroPythonDevices import MicroPythonDevice |
21 from .MicroPythonDevices import FirmwareGithubUrls, MicroPythonDevice |
21 from .MicroPythonWidget import HAS_QTCHART |
22 from .MicroPythonWidget import HAS_QTCHART |
22 |
23 |
23 |
24 |
24 class EspDevice(MicroPythonDevice): |
25 class EspDevice(MicroPythonDevice): |
25 """ |
26 """ |
123 |
124 |
124 @param menu reference to the context menu |
125 @param menu reference to the context menu |
125 @type QMenu |
126 @type QMenu |
126 """ |
127 """ |
127 connected = self.microPython.isConnected() |
128 connected = self.microPython.isConnected() |
128 |
129 linkConnected = self.microPython.isLinkConnected() |
129 act = menu.addAction(self.tr("Erase Flash"), self.__eraseFlash) |
130 |
130 act.setEnabled(not connected) |
131 menu.addAction( |
131 act = menu.addAction( |
132 self.tr("Show MicroPython Versions"), self.__showFirmwareVersions |
|
133 ).setEnabled(connected) |
|
134 menu.addAction(self.tr("Erase Flash"), self.__eraseFlash).setEnabled( |
|
135 not linkConnected |
|
136 ) |
|
137 menu.addAction( |
132 self.tr("Flash MicroPython Firmware"), self.__flashMicroPython |
138 self.tr("Flash MicroPython Firmware"), self.__flashMicroPython |
133 ) |
139 ).setEnabled(not linkConnected) |
134 act.setEnabled(not connected) |
|
135 menu.addSeparator() |
140 menu.addSeparator() |
136 act = menu.addAction(self.tr("Flash Additional Firmware"), self.__flashAddons) |
141 menu.addAction( |
137 act.setEnabled(not connected) |
142 self.tr("Flash Additional Firmware"), self.__flashAddons |
|
143 ).setEnabled(not linkConnected) |
138 menu.addSeparator() |
144 menu.addSeparator() |
139 act = menu.addAction(self.tr("Backup Firmware"), self.__backupFlash) |
145 menu.addAction(self.tr("Backup Firmware"), self.__backupFlash).setEnabled( |
140 act.setEnabled(not connected) |
146 not linkConnected |
141 act = menu.addAction(self.tr("Restore Firmware"), self.__restoreFlash) |
147 ) |
142 act.setEnabled(not connected) |
148 menu.addAction(self.tr("Restore Firmware"), self.__restoreFlash).setEnabled( |
|
149 not linkConnected |
|
150 ) |
143 menu.addSeparator() |
151 menu.addSeparator() |
144 act = menu.addAction(self.tr("Show Chip ID"), self.__showChipID) |
152 menu.addAction(self.tr("Show Chip ID"), self.__showChipID).setEnabled( |
145 act.setEnabled(not connected) |
153 not linkConnected |
146 act = menu.addAction(self.tr("Show Flash ID"), self.__showFlashID) |
154 ) |
147 act.setEnabled(not connected) |
155 menu.addAction(self.tr("Show Flash ID"), self.__showFlashID).setEnabled( |
148 act = menu.addAction(self.tr("Show MAC Address"), self.__showMACAddress) |
156 not linkConnected |
149 act.setEnabled(not connected) |
157 ) |
|
158 menu.addAction(self.tr("Show MAC Address"), self.__showMACAddress).setEnabled( |
|
159 not linkConnected |
|
160 ) |
150 menu.addSeparator() |
161 menu.addSeparator() |
151 act = menu.addAction(self.tr("Reset Device"), self.__resetDevice) |
162 menu.addAction(self.tr("Reset Device"), self.__resetDevice).setEnabled( |
|
163 connected or not linkConnected |
|
164 ) |
152 menu.addSeparator() |
165 menu.addSeparator() |
153 menu.addAction(self.tr("Install 'esptool.py'"), self.__installEspTool) |
166 menu.addAction(self.tr("Install 'esptool.py'"), self.__installEspTool) |
154 |
167 |
155 def hasFlashMenuEntry(self): |
168 def hasFlashMenuEntry(self): |
156 """ |
169 """ |
347 res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs) |
360 res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs) |
348 if res: |
361 if res: |
349 dlg.exec() |
362 dlg.exec() |
350 |
363 |
351 @pyqtSlot() |
364 @pyqtSlot() |
|
365 def __showFirmwareVersions(self): |
|
366 """ |
|
367 Private slot to show the firmware version of the connected device and the |
|
368 available firmware version. |
|
369 """ |
|
370 if self.microPython.isConnected(): |
|
371 interface = self.microPython.commandsInterface() |
|
372 if interface is not None: |
|
373 impInfo = interface.getImplementation() |
|
374 if impInfo["name"] != "micropython": |
|
375 EricMessageBox.critical( |
|
376 None, |
|
377 self.tr("Show MicroPython Versions"), |
|
378 self.tr( |
|
379 """The firmware of the connected device cannot be""" |
|
380 """ determined or the board does not run MicroPython.""" |
|
381 """ Aborting...""" |
|
382 ), |
|
383 ) |
|
384 else: |
|
385 ui = ericApp().getObject("UserInterface") |
|
386 request = QNetworkRequest(QUrl(FirmwareGithubUrls["micropython"])) |
|
387 reply = ui.networkAccessManager().head(request) |
|
388 reply.finished.connect( |
|
389 lambda: self.__firmwareVersionResponse(reply, impInfo) |
|
390 ) |
|
391 |
|
392 def __firmwareVersionResponse(self, reply, implementation): |
|
393 """ |
|
394 Private method handling the response of the latest version request. |
|
395 |
|
396 @param reply reference to the reply object |
|
397 @type QNetworkReply |
|
398 @param implementation dictionary containing the implementation data of the |
|
399 connected device |
|
400 @type dict |
|
401 """ |
|
402 latestUrl = reply.url().toString() |
|
403 tag = latestUrl.rsplit("/", 1)[-1] |
|
404 while tag and not tag[0].isdecimal(): |
|
405 # get rid of leading non-decimal characters |
|
406 tag = tag[1:] |
|
407 latestVersion = Globals.versionToTuple(tag) |
|
408 |
|
409 if implementation["version"] == "unknown": |
|
410 currentVersionStr = self.tr("unknown") |
|
411 currentVersion = (0, 0, 0) |
|
412 else: |
|
413 currentVersionStr = implementation["version"] |
|
414 currentVersion = Globals.versionToTuple(currentVersionStr) |
|
415 |
|
416 msg = self.tr( |
|
417 "<h4>MicroPython Version Information</h4>" |
|
418 "<table>" |
|
419 "<tr><td>Installed:</td><td>{0}</td></tr>" |
|
420 "<tr><td>Available:</td><td>{1}</td></tr>" |
|
421 "</table>" |
|
422 ).format(currentVersionStr, tag) |
|
423 if currentVersion < latestVersion: |
|
424 msg += self.tr("<p><b>Update available!</b></p>") |
|
425 |
|
426 EricMessageBox.information( |
|
427 None, |
|
428 self.tr("MicroPython Version"), |
|
429 msg, |
|
430 ) |
|
431 |
|
432 @pyqtSlot() |
352 def __showChipID(self): |
433 def __showChipID(self): |
353 """ |
434 """ |
354 Private slot to show the ID of the ESP chip. |
435 Private slot to show the ID of the ESP chip. |
355 """ |
436 """ |
356 args = [ |
437 args = [ |