7 Module implementing the device interface class for PyBoard boards. |
7 Module implementing the device interface class for PyBoard boards. |
8 """ |
8 """ |
9 |
9 |
10 import os |
10 import os |
11 |
11 |
12 from PyQt6.QtCore import QStandardPaths, pyqtSlot |
12 from PyQt6.QtCore import QStandardPaths, QUrl, pyqtSlot |
13 |
13 from PyQt6.QtNetwork import QNetworkRequest |
14 from eric7 import Preferences |
14 |
|
15 from eric7 import Globals, Preferences |
15 from eric7.EricWidgets import EricFileDialog, EricMessageBox |
16 from eric7.EricWidgets import EricFileDialog, 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 FileSystemUtilities |
19 from eric7.SystemUtilities import FileSystemUtilities |
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 PyBoardDevice(MicroPythonDevice): |
25 class PyBoardDevice(MicroPythonDevice): |
25 """ |
26 """ |
226 |
227 |
227 @param menu reference to the context menu |
228 @param menu reference to the context menu |
228 @type QMenu |
229 @type QMenu |
229 """ |
230 """ |
230 connected = self.microPython.isConnected() |
231 connected = self.microPython.isConnected() |
231 |
232 linkConnected = self.microPython.isLinkConnected() |
232 act = menu.addAction(self.tr("Activate Bootloader"), self.__activateBootloader) |
233 |
233 act.setEnabled(connected) |
234 menu.addAction( |
234 act = menu.addAction( |
235 self.tr("Activate Bootloader"), self.__activateBootloader |
|
236 ).setEnabled(connected) |
|
237 menu.addAction( |
235 self.tr("List DFU-capable Devices"), self.__listDfuCapableDevices |
238 self.tr("List DFU-capable Devices"), self.__listDfuCapableDevices |
236 ) |
239 ).setEnabled(not linkConnected) |
237 act.setEnabled(not connected) |
240 menu.addSeparator() |
238 act = menu.addAction( |
241 menu.addAction( |
|
242 self.tr("Show MicroPython Versions"), self.__showFirmwareVersions |
|
243 ).setEnabled(connected) |
|
244 menu.addAction( |
239 self.tr("Flash MicroPython Firmware"), self.__flashMicroPython |
245 self.tr("Flash MicroPython Firmware"), self.__flashMicroPython |
240 ) |
246 ).setEnabled(not linkConnected) |
241 act.setEnabled(not connected) |
|
242 menu.addSeparator() |
|
243 menu.addAction( |
247 menu.addAction( |
244 self.tr("MicroPython Flash Instructions"), self.__showFlashInstructions |
248 self.tr("MicroPython Flash Instructions"), self.__showFlashInstructions |
245 ) |
249 ) |
246 |
250 |
247 def hasFlashMenuEntry(self): |
251 def hasFlashMenuEntry(self): |
402 if res: |
406 if res: |
403 dlg.exec() |
407 dlg.exec() |
404 self.__showDfuDisableInstructions() |
408 self.__showDfuDisableInstructions() |
405 |
409 |
406 @pyqtSlot() |
410 @pyqtSlot() |
|
411 def __showFirmwareVersions(self): |
|
412 """ |
|
413 Private slot to show the firmware version of the connected device and the |
|
414 available firmware version. |
|
415 """ |
|
416 if self.microPython.isConnected(): |
|
417 interface = self.microPython.commandsInterface() |
|
418 if interface is not None: |
|
419 impInfo = interface.getImplementation() |
|
420 if impInfo["name"] != "micropython": |
|
421 EricMessageBox.critical( |
|
422 None, |
|
423 self.tr("Show MicroPython Versions"), |
|
424 self.tr( |
|
425 """The firmware of the connected device cannot be""" |
|
426 """ determined or the board does not run MicroPython.""" |
|
427 """ Aborting...""" |
|
428 ), |
|
429 ) |
|
430 else: |
|
431 ui = ericApp().getObject("UserInterface") |
|
432 request = QNetworkRequest(QUrl(FirmwareGithubUrls["micropython"])) |
|
433 reply = ui.networkAccessManager().head(request) |
|
434 reply.finished.connect( |
|
435 lambda: self.__firmwareVersionResponse(reply, impInfo) |
|
436 ) |
|
437 |
|
438 def __firmwareVersionResponse(self, reply, implementation): |
|
439 """ |
|
440 Private method handling the response of the latest version request. |
|
441 |
|
442 @param reply reference to the reply object |
|
443 @type QNetworkReply |
|
444 @param implementation dictionary containing the implementation data of the |
|
445 connected device |
|
446 @type dict |
|
447 """ |
|
448 latestUrl = reply.url().toString() |
|
449 tag = latestUrl.rsplit("/", 1)[-1] |
|
450 while tag and not tag[0].isdecimal(): |
|
451 # get rid of leading non-decimal characters |
|
452 tag = tag[1:] |
|
453 latestVersion = Globals.versionToTuple(tag) |
|
454 |
|
455 if implementation["version"] == "unknown": |
|
456 currentVersionStr = self.tr("unknown") |
|
457 currentVersion = (0, 0, 0) |
|
458 else: |
|
459 currentVersionStr = implementation["version"] |
|
460 currentVersion = Globals.versionToTuple(currentVersionStr) |
|
461 |
|
462 msg = self.tr( |
|
463 "<h4>MicroPython Version Information</h4>" |
|
464 "<table>" |
|
465 "<tr><td>Installed:</td><td>{0}</td></tr>" |
|
466 "<tr><td>Available:</td><td>{1}</td></tr>" |
|
467 "</table>" |
|
468 ).format(currentVersionStr, tag) |
|
469 if currentVersion < latestVersion: |
|
470 msg += self.tr("<p><b>Update available!</b></p>") |
|
471 |
|
472 EricMessageBox.information( |
|
473 None, |
|
474 self.tr("MicroPython Version"), |
|
475 msg, |
|
476 ) |
|
477 |
|
478 @pyqtSlot() |
407 def __activateBootloader(self): |
479 def __activateBootloader(self): |
408 """ |
480 """ |
409 Private slot to activate the bootloader and disconnect. |
481 Private slot to activate the bootloader and disconnect. |
410 """ |
482 """ |
411 if self.microPython.isConnected(): |
483 if self.microPython.isConnected(): |