MicroPython mpy_network

Mon, 27 Feb 2023 17:43:11 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 27 Feb 2023 17:43:11 +0100
branch
mpy_network
changeset 9820
67597e003373
parent 9817
640b6c23d97b
child 9821
6b1b06d74532

MicroPython
- did some corrections to the device interface modules

src/eric7/MicroPython/Devices/CircuitPythonDevices.py file | annotate | diff | comparison | revisions
src/eric7/MicroPython/Devices/EspDevices.py file | annotate | diff | comparison | revisions
src/eric7/MicroPython/Devices/EspDialogs/EspFirmwareSelectionDialog.ui file | annotate | diff | comparison | revisions
src/eric7/MicroPython/Devices/MicrobitDevices.py file | annotate | diff | comparison | revisions
src/eric7/MicroPython/Devices/PyBoardDevices.py file | annotate | diff | comparison | revisions
src/eric7/MicroPython/Devices/RP2040Devices.py file | annotate | diff | comparison | revisions
src/eric7/MicroPython/Devices/TeensyDevices.py file | annotate | diff | comparison | revisions
--- a/src/eric7/MicroPython/Devices/CircuitPythonDevices.py	Mon Feb 27 16:55:09 2023 +0100
+++ b/src/eric7/MicroPython/Devices/CircuitPythonDevices.py	Mon Feb 27 17:43:11 2023 +0100
@@ -7,11 +7,13 @@
 Module implementing the device interface class for CircuitPython boards.
 """
 
+import ast
+import json
 import os
 import shutil
 
-from PyQt6.QtCore import QProcess, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtCore import QUrl, pyqtSlot
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QMenu
 
 from eric7 import Globals, Preferences
@@ -69,6 +71,9 @@
         if not connected and self.__libraryMenu.isTearOffMenuVisible():
             self.__libraryMenu.hideTearOffMenu()
 
+        if self.__flashMenu.isTearOffMenuVisible():
+            self.__flashMenu.hideTearOffMenu()
+
         super().setConnected(connected)
 
     def setButtons(self):
@@ -262,33 +267,14 @@
         self.__libraryMenu.aboutToShow.connect(self.__aboutToShowLibraryMenu)
         self.__libraryMenu.setTearOffEnabled(True)
 
+        self.__flashMenu = self.__createFlashMenus()
+
         self.__cpyMenu = QMenu(self.tr("CircuitPython Functions"))
-
         self.__cpyMenu.addAction(
             self.tr("Show CircuitPython Versions"), self.__showCircuitPythonVersions
         )
         self.__cpyMenu.addSeparator()
-
-        boardName = self.microPython.getCurrentBoard()
-        lBoardName = boardName.lower() if boardName else ""
-        if "teensy" in lBoardName:
-            # Teensy 4.0 and 4.1 don't support UF2 flashing
-            self.__cpyMenu.addAction(
-                self.tr("CircuitPython Flash Instructions"),
-                self.__showTeensyFlashInstructions,
-            )
-            self.__flashCpyAct = self.__cpyMenu.addAction(
-                self.tr("Flash CircuitPython Firmware"), self.__startTeensyLoader
-            )
-            self.__flashCpyAct.setToolTip(
-                self.tr(
-                    "Start the 'Teensy Loader' application to flash the Teensy device."
-                )
-            )
-        else:
-            self.__flashCpyAct = self.__cpyMenu.addAction(
-                self.tr("Flash CircuitPython Firmware"), self.__flashCircuitPython
-            )
+        self.__flashCpyAct = self.__cpyMenu.addMenu(self.__flashMenu)
         self.__cpyMenu.addSeparator()
         self.__cpyMenu.addMenu(self.__libraryMenu)
         self.__cpyMenu.addSeparator()
@@ -296,6 +282,48 @@
             self.tr("Reset Device"), self.__resetDevice
         )
 
+    def __createFlashMenus(self):
+        """
+        Private method to create the various menus to flash a CircuitPython firmware.
+
+        @return reference to the created top level flash menu
+        @rtype QMenu
+        """
+        menu = QMenu(self.tr("Flash CircuitPython Firmware"))
+        menu.setTearOffEnabled(True)
+
+        # UF2 devices
+        menu.addAction(self.tr("UF2 Device"), self.__flashCircuitPython)
+        menu.addSeparator()
+
+        # ESP32 specific submenu
+        self.__esp32FlashMenu = QMenu(self.tr("ESP32 Device"))
+        self.__esp32FlashMenu.addAction(self.tr("Erase Flash"), self.__esp32EraseFlash)
+        self.__esp32FlashMenu.addAction(
+            self.tr("Flash MicroPython Firmware"), self.__esp32FlashPython
+        )
+        self.__esp32FlashMenu.addSeparator()
+        self.__esp32FlashMenu.addAction(
+            self.tr("Flash Additional Firmware"), self.__esp32FlashAddons
+        )
+        menu.addMenu(self.__esp32FlashMenu)
+
+        # Teensy 4.0 and 4.1 specific submenu
+        self.__teensyFlashMenu = QMenu(self.tr("Teensy Device"))
+        self.__teensyFlashMenu.addAction(
+            self.tr("CircuitPython Flash Instructions"),
+            self.__showTeensyFlashInstructions,
+        )
+        act = self.__teensyFlashMenu.addAction(
+            self.tr("Start 'Teensy Loader'"), self.__startTeensyLoader
+        )
+        act.setToolTip(
+            self.tr("Start the 'Teensy Loader' application to flash the Teensy device.")
+        )
+        menu.addMenu(self.__teensyFlashMenu)
+
+        return menu
+
     def addDeviceMenuEntries(self, menu):
         """
         Public method to add device specific entries to the given menu.
@@ -365,41 +393,54 @@
         dlg = UF2FlashDialog(boardType="circuitpython")
         dlg.exec()
 
+    @pyqtSlot()
     def __showTeensyFlashInstructions(self):
         """
-        Private method to show a message box because Teensy does not support
+        Private slot to show a message box because Teensy does not support
         the UF2 bootloader yet.
         """
-        EricMessageBox.information(
-            self.microPython,
-            self.tr("Flash CircuitPython Firmware"),
-            self.tr(
-                """<p>Teensy 4.0 and Teensy 4.1 do not support the UF2"""
-                """ bootloader. Please use the 'Teensy Loader'"""
-                """ application to flash CircuitPython. Make sure you"""
-                """ downloaded the CircuitPython .hex file.</p>"""
-                """<p>See <a href="{0}">the PJRC Teensy web site</a>"""
-                """ for details.</p>"""
-            ).format("https://www.pjrc.com/teensy/loader.html"),
-        )
+        from .TeensyDevices import showTeensyFlashInstructions
 
+        showTeensyFlashInstructions()
+
+    @pyqtSlot()
     def __startTeensyLoader(self):
         """
-        Private method to start the 'Teensy Loader' application.
+        Private slot to start the 'Teensy Loader' application.
 
         Note: The application must be accessible via the application search path.
         """
-        ok, _ = QProcess.startDetached("teensy")
-        if not ok:
-            EricMessageBox.warning(
-                self.microPython,
-                self.tr("Start 'Teensy Loader'"),
-                self.tr(
-                    """<p>The 'Teensy Loader' application <b>teensy</b> could not"""
-                    """ be started. Ensure it is in the application search path or"""
-                    """ start it manually.</p>"""
-                ),
-            )
+        from .TeensyDevices import startTeensyLoader
+
+        startTeensyLoader()
+
+    @pyqtSlot()
+    def __esp32EraseFlash(self):
+        """
+        Private slot to erase the flash of an ESP32 device.
+        """
+        from .EspDevices import eraseFlash
+
+        eraseFlash(self.microPython.getCurrentPort())
+
+    @pyqtSlot()
+    def __esp32FlashPython(self):
+        """
+        Private slot to flash a MicroPython or CircuitPython firmware to an ESP32
+        device.
+        """
+        from .EspDevices import flashPythonFirmware
+
+        flashPythonFirmware(self.microPython.getCurrentPort())
+
+    @pyqtSlot()
+    def __esp32FlashAddons(self):
+        """
+        Private slot to flash additional firmware to an ESP32 device.
+        """
+        from .EspDevices import flashAddonFirmware
+
+        flashAddonFirmware(self.microPython.getCurrentPort())
 
     @pyqtSlot()
     def __showCircuitPythonVersions(self):
@@ -412,9 +453,10 @@
         reply = ui.networkAccessManager().head(request)
         reply.finished.connect(lambda: self.__cpyVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __cpyVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
@@ -543,6 +585,104 @@
             ),
         ]
 
+    ##################################################################
+    ## Methods below implement WiFi related methods
+    ##################################################################
+
+    def hasWifi(self):
+        """
+        Public method to check the availability of WiFi.
+
+        @return tuple containing a flag indicating the availability of WiFi
+            and the WiFi type (picow or pimoroni)
+        @rtype tuple of (bool, str)
+        @exception OSError raised to indicate an issue with the device
+        """
+        command = """
+def has_wifi():
+    try:
+        import wifi
+        if hasattr(wifi, 'radio'):
+            return True, 'circuitpython'
+    except ImportError:
+        pass
+
+    return False, ''
+
+print(has_wifi())
+del has_wifi
+"""
+        out, err = self._interface.execute(command, mode=self.submitMode)
+        if err:
+            raise OSError(self._shortError(err))
+        return ast.literal_eval(out.decode("utf-8"))
+
+    def getWifiData(self):
+        """
+        Public method to get data related to the current WiFi status.
+
+        @return tuple of three dictionaries containing the WiFi status data
+            for the WiFi client, access point and overall data
+        @rtype tuple of (dict, dict, dict)
+        @exception OSError raised to indicate an issue with the device
+        """
+        command = """
+def wifi_status():
+    import binascii
+    import json
+    import wifi
+
+    r = wifi.radio
+
+    station = {
+        'active': r.enabled and r.ipv4_address_ap is None,
+        'connected': r.ipv4_address is not None,
+        'ifconfig': (
+            str(r.ipv4_address) if r.ipv4_address else'0.0.0.0',
+            str(r.ipv4_subnet) if r.ipv4_subnet else'0.0.0.0',
+            str(r.ipv4_gateway) if r.ipv4_gateway else'0.0.0.0',
+            str(r.ipv4_dns) if r.ipv4_dns else'0.0.0.0',
+        ),
+        'mac': binascii.hexlify(r.mac_address, ':').decode(),
+        'txpower': r.tx_power,
+        'hostname': r.hostname,
+    }
+    print(json.dumps(station))
+
+    ap = {
+        'active': r.enabled and r.ipv4_address_ap is not None,
+        'connected': r.ipv4_address_ap is not None,
+        'ifconfig': (
+            str(r.ipv4_address_ap) if r.ipv4_address_ap else'0.0.0.0',
+            str(r.ipv4_subnet_ap) if r.ipv4_subnet_ap else'0.0.0.0',
+            str(r.ipv4_gateway_ap) if r.ipv4_gateway_ap else'0.0.0.0',
+            str(r.ipv4_dns) if r.ipv4_dns else'0.0.0.0',
+        ),
+        'mac': binascii.hexlify(r.mac_address_ap, ':').decode(),
+        'txpower': r.tx_power,
+        'hostname': r.hostname,
+    }
+    print(json.dumps(ap))
+
+    overall = {
+        'active': r.enabled
+    }
+    print(json.dumps(overall))
+
+wifi_status()
+del wifi_status
+"""
+
+        out, err = self._interface.execute(command, mode=self.submitMode)
+        if err:
+            raise OSError(self._shortError(err))
+
+        stationStr, apStr, overallStr = out.decode("utf-8").splitlines()
+        station = json.loads(stationStr)
+        ap = json.loads(apStr)
+        overall = json.loads(overallStr)
+        return station, ap, overall
+
 
 def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber):
     """
--- a/src/eric7/MicroPython/Devices/EspDevices.py	Mon Feb 27 16:55:09 2023 +0100
+++ b/src/eric7/MicroPython/Devices/EspDevices.py	Mon Feb 27 17:43:11 2023 +0100
@@ -13,8 +13,8 @@
 import json
 import os
 
-from PyQt6.QtCore import QProcess, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtCore import QCoreApplication, QProcess, QUrl, pyqtSlot
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QDialog, QMenu
 
 from eric7 import Globals, Preferences
@@ -230,102 +230,21 @@
         """
         Private slot to erase the device flash memory.
         """
-        ok = EricMessageBox.yesNo(
-            self.microPython,
-            self.tr("Erase Flash"),
-            self.tr("""Shall the flash of the selected device really be erased?"""),
-        )
-        if ok:
-            flashArgs = [
-                "-u",
-                "-m",
-                "esptool",
-                "--port",
-                self.microPython.getCurrentPort(),
-                "erase_flash",
-            ]
-            dlg = EricProcessDialog(
-                self.tr("'esptool erase_flash' Output"),
-                self.tr("Erase Flash"),
-                showProgress=True,
-            )
-            res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
-            if res:
-                dlg.exec()
+        eraseFlash(self.microPython.getCurrentPort())
 
     @pyqtSlot()
     def __flashMicroPython(self):
         """
         Private slot to flash a MicroPython firmware to the device.
         """
-        from .EspDialogs.EspFirmwareSelectionDialog import EspFirmwareSelectionDialog
-
-        dlg = EspFirmwareSelectionDialog()
-        if dlg.exec() == QDialog.DialogCode.Accepted:
-            chip, firmware, baudRate, flashMode, flashAddress = dlg.getData()
-            flashArgs = [
-                "-u",
-                "-m",
-                "esptool",
-                "--chip",
-                chip,
-                "--port",
-                self.microPython.getCurrentPort(),
-            ]
-            if baudRate != "115200":
-                flashArgs += ["--baud", baudRate]
-            flashArgs.append("write_flash")
-            if flashMode:
-                flashArgs += ["--flash_mode", flashMode]
-            flashArgs += [
-                flashAddress,
-                firmware,
-            ]
-            dlg = EricProcessDialog(
-                self.tr("'esptool write_flash' Output"),
-                self.tr("Flash MicroPython Firmware"),
-                showProgress=True,
-            )
-            res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
-            if res:
-                dlg.exec()
+        flashPythonFirmware(self.microPython.getCurrentPort())
 
     @pyqtSlot()
     def __flashAddons(self):
         """
         Private slot to flash some additional firmware images.
         """
-        from .EspDialogs.EspFirmwareSelectionDialog import EspFirmwareSelectionDialog
-
-        dlg = EspFirmwareSelectionDialog(addon=True)
-        if dlg.exec() == QDialog.DialogCode.Accepted:
-            chip, firmware, baudRate, flashMode, flashAddress = dlg.getData()
-            flashArgs = [
-                "-u",
-                "-m",
-                "esptool",
-                "--chip",
-                chip,
-                "--port",
-                self.microPython.getCurrentPort(),
-            ]
-            if baudRate != "115200":
-                flashArgs += ["--baud", baudRate]
-            flashArgs.append("write_flash")
-            if flashMode:
-                flashArgs += ["--flash_mode", flashMode]
-            flashArgs += [
-                flashAddress.lower(),
-                firmware,
-            ]
-            dlg = EricProcessDialog(
-                self.tr("'esptool write_flash' Output"),
-                self.tr("Flash Additional Firmware"),
-                showProgress=True,
-            )
-            res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
-            if res:
-                dlg.exec()
+        flashAddonFirmware(self.microPython.getCurrentPort())
 
     @pyqtSlot()
     def __backupFlash(self):
@@ -444,9 +363,10 @@
             reply = ui.networkAccessManager().head(request)
             reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
@@ -1133,3 +1053,125 @@
     @rtype EspDevice
     """
     return EspDevice(microPythonWidget, deviceType)
+
+
+################################################################################
+## Functions below implement flashing related functionality needed elsewhere  ##
+## as well.                                                                   ##
+################################################################################
+
+
+@pyqtSlot()
+def eraseFlash(port):
+    """
+    Slot to erase the device flash memory.
+
+    @param port name of the serial port device to be used
+    @type str
+    """
+    ok = EricMessageBox.yesNo(
+        None,
+        QCoreApplication.translate("EspDevice", "Erase Flash"),
+        QCoreApplication.translate(
+            "EspDevice", """Shall the flash of the selected device really be erased?"""
+        ),
+    )
+    if ok:
+        flashArgs = [
+            "-u",
+            "-m",
+            "esptool",
+            "--port",
+            port,
+            "erase_flash",
+        ]
+        dlg = EricProcessDialog(
+            QCoreApplication.translate("EspDevice", "'esptool erase_flash' Output"),
+            QCoreApplication.translate("EspDevice", "Erase Flash"),
+            showProgress=True,
+        )
+        res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
+        if res:
+            dlg.exec()
+
+
+@pyqtSlot()
+def flashPythonFirmware(port):
+    """
+    Slot to flash a MicroPython firmware to the device.
+
+    @param port name of the serial port device to be used
+    @type str
+    """
+    from .EspDialogs.EspFirmwareSelectionDialog import EspFirmwareSelectionDialog
+
+    dlg = EspFirmwareSelectionDialog()
+    if dlg.exec() == QDialog.DialogCode.Accepted:
+        chip, firmware, baudRate, flashMode, flashAddress = dlg.getData()
+        flashArgs = [
+            "-u",
+            "-m",
+            "esptool",
+            "--chip",
+            chip,
+            "--port",
+            port,
+        ]
+        if baudRate != "115200":
+            flashArgs += ["--baud", baudRate]
+        flashArgs.append("write_flash")
+        if flashMode:
+            flashArgs += ["--flash_mode", flashMode]
+        flashArgs += [
+            flashAddress,
+            firmware,
+        ]
+        dlg = EricProcessDialog(
+            QCoreApplication.translate("EspDevice", "'esptool write_flash' Output"),
+            QCoreApplication.translate("EspDevice", "Flash µPy/CPy Firmware"),
+            showProgress=True,
+        )
+        res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
+        if res:
+            dlg.exec()
+
+
+@pyqtSlot()
+def flashAddonFirmware(port):
+    """
+    Slot to flash some additional firmware images.
+
+    @param port name of the serial port device to be used
+    @type str
+    """
+    from .EspDialogs.EspFirmwareSelectionDialog import EspFirmwareSelectionDialog
+
+    dlg = EspFirmwareSelectionDialog(addon=True)
+    if dlg.exec() == QDialog.DialogCode.Accepted:
+        chip, firmware, baudRate, flashMode, flashAddress = dlg.getData()
+        flashArgs = [
+            "-u",
+            "-m",
+            "esptool",
+            "--chip",
+            chip,
+            "--port",
+            port,
+        ]
+        if baudRate != "115200":
+            flashArgs += ["--baud", baudRate]
+        flashArgs.append("write_flash")
+        if flashMode:
+            flashArgs += ["--flash_mode", flashMode]
+        flashArgs += [
+            flashAddress.lower(),
+            firmware,
+        ]
+        dlg = EricProcessDialog(
+            QCoreApplication.translate("EspDevice", "'esptool write_flash' Output"),
+            QCoreApplication.translate("EspDevice", "Flash Additional Firmware"),
+            showProgress=True,
+        )
+        res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
+        if res:
+            dlg.exec()
--- a/src/eric7/MicroPython/Devices/EspDialogs/EspFirmwareSelectionDialog.ui	Mon Feb 27 16:55:09 2023 +0100
+++ b/src/eric7/MicroPython/Devices/EspDialogs/EspFirmwareSelectionDialog.ui	Mon Feb 27 17:43:11 2023 +0100
@@ -11,7 +11,7 @@
    </rect>
   </property>
   <property name="windowTitle">
-   <string>Flash MicroPython Firmware</string>
+   <string>Flash µPy/CPy Firmware</string>
   </property>
   <property name="sizeGripEnabled">
    <bool>true</bool>
--- a/src/eric7/MicroPython/Devices/MicrobitDevices.py	Mon Feb 27 16:55:09 2023 +0100
+++ b/src/eric7/MicroPython/Devices/MicrobitDevices.py	Mon Feb 27 17:43:11 2023 +0100
@@ -14,7 +14,7 @@
 import shutil
 
 from PyQt6.QtCore import QStandardPaths, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QMenu
 
 from eric7 import Globals, Preferences
@@ -424,9 +424,10 @@
                 reply = ui.networkAccessManager().head(request)
                 reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
--- a/src/eric7/MicroPython/Devices/PyBoardDevices.py	Mon Feb 27 16:55:09 2023 +0100
+++ b/src/eric7/MicroPython/Devices/PyBoardDevices.py	Mon Feb 27 17:43:11 2023 +0100
@@ -10,7 +10,7 @@
 import os
 
 from PyQt6.QtCore import QStandardPaths, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QMenu
 
 from eric7 import Globals, Preferences
@@ -449,9 +449,10 @@
                 reply = ui.networkAccessManager().head(request)
                 reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
--- a/src/eric7/MicroPython/Devices/RP2040Devices.py	Mon Feb 27 16:55:09 2023 +0100
+++ b/src/eric7/MicroPython/Devices/RP2040Devices.py	Mon Feb 27 17:43:11 2023 +0100
@@ -14,7 +14,7 @@
 import os
 
 from PyQt6.QtCore import QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QDialog, QMenu
 
 from eric7 import Globals, Preferences
@@ -203,9 +203,10 @@
         dlg = UF2FlashDialog(boardType="rp2040")
         dlg.exec()
 
+    @pyqtSlot()
     def __activateBootloader(self):
         """
-        Private method to switch the board into 'bootloader' mode.
+        Private slot to switch the board into 'bootloader' mode.
         """
         if self.microPython.isConnected():
             self.microPython.deviceInterface().execute(
@@ -245,9 +246,10 @@
                 reply = ui.networkAccessManager().head(request)
                 reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
--- a/src/eric7/MicroPython/Devices/TeensyDevices.py	Mon Feb 27 16:55:09 2023 +0100
+++ b/src/eric7/MicroPython/Devices/TeensyDevices.py	Mon Feb 27 17:43:11 2023 +0100
@@ -7,8 +7,8 @@
 Module implementing the device interface class for Teensy boards with MicroPython.
 """
 
-from PyQt6.QtCore import QProcess, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtCore import QCoreApplication, QProcess, QUrl, pyqtSlot
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QMenu
 
 from eric7 import Globals, Preferences
@@ -148,10 +148,10 @@
         )
         self.__teensyMenu.addSeparator()
         self.__teensyMenu.addAction(
-            self.tr("MicroPython Flash Instructions"), self.__showFlashInstructions
+            self.tr("MicroPython Flash Instructions"), showTeensyFlashInstructions
         )
         self.__flashMpyAct = self.__teensyMenu.addAction(
-            self.tr("Flash MicroPython Firmware"), self.__startTeensyLoader
+            self.tr("Flash MicroPython Firmware"), startTeensyLoader
         )
         self.__flashMpyAct.setToolTip(
             self.tr("Start the 'Teensy Loader' application to flash the Teensy device.")
@@ -195,9 +195,10 @@
                 reply = ui.networkAccessManager().head(request)
                 reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
@@ -232,40 +233,6 @@
             msg,
         )
 
-    def __showFlashInstructions(self):
-        """
-        Private method to show a message box with instruction to flash the Teensy.
-        """
-        EricMessageBox.information(
-            self.microPython,
-            self.tr("Flash MicroPython Firmware"),
-            self.tr(
-                """<p>Teensy 4.0 and Teensy 4.1 are flashed using the 'Teensy Loader'"""
-                """ application. Make sure you downloaded the MicroPython or"""
-                """ CircuitPython .hex file.</p>"""
-                """<p>See <a href="{0}">the PJRC Teensy web site</a>"""
-                """ for details.</p>"""
-            ).format("https://www.pjrc.com/teensy/loader.html"),
-        )
-
-    def __startTeensyLoader(self):
-        """
-        Private method to start the 'Teensy Loader' application.
-
-        Note: The application must be accessible via the application search path.
-        """
-        ok, _ = QProcess.startDetached("teensy")
-        if not ok:
-            EricMessageBox.warning(
-                self.microPython,
-                self.tr("Start 'Teensy Loader'"),
-                self.tr(
-                    """<p>The 'Teensy Loader' application <b>teensy</b> could not"""
-                    """ be started. Ensure it is in the application search path or"""
-                    """ start it manually.</p>"""
-                ),
-            )
-
     ##################################################################
     ## time related methods below
     ##################################################################
@@ -322,3 +289,43 @@
     @rtype PyBoardDevice
     """
     return TeensyDevice(microPythonWidget, deviceType)
+
+
+@pyqtSlot()
+def showTeensyFlashInstructions():
+    """
+    Slot to show a message box with instruction to flash the Teensy.
+    """
+    EricMessageBox.information(
+        None,
+        QCoreApplication.translate("TeensyDevice", "Flash MicroPython Firmware"),
+        QCoreApplication.translate(
+            "TeensyDevice",
+            """<p>Teensy 4.0 and Teensy 4.1 are flashed using the 'Teensy Loader'"""
+            """ application. Make sure you downloaded the MicroPython or"""
+            """ CircuitPython .hex file.</p>"""
+            """<p>See <a href="{0}">the PJRC Teensy web site</a>"""
+            """ for details.</p>""",
+        ).format("https://www.pjrc.com/teensy/loader.html"),
+    )
+
+
+@pyqtSlot()
+def startTeensyLoader():
+    """
+    Slot to start the 'Teensy Loader' application.
+
+    Note: The application must be accessible via the application search path.
+    """
+    ok, _ = QProcess.startDetached("teensy")
+    if not ok:
+        EricMessageBox.warning(
+            None,
+            QCoreApplication.translate("TeensyDevice", "Start 'Teensy Loader'"),
+            QCoreApplication.translate(
+                "TeensyDevice",
+                """<p>The 'Teensy Loader' application <b>teensy</b> could not"""
+                """ be started. Ensure it is in the application search path or"""
+                """ start it manually.</p>""",
+            ),
+        )

eric ide

mercurial