src/eric7/MicroPython/Devices/DeviceBase.py

branch
eric7
changeset 9756
9854647c8c5c
parent 9755
1a09700229e7
child 9763
52f982c08301
diff -r 1a09700229e7 -r 9854647c8c5c src/eric7/MicroPython/Devices/DeviceBase.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/Devices/DeviceBase.py	Mon Feb 13 17:49:52 2023 +0100
@@ -0,0 +1,362 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing some utility functions and the MicroPythonDevice base
+class.
+"""
+
+import contextlib
+import copy
+import os
+
+from PyQt6.QtCore import QObject, pyqtSlot
+from PyQt6.QtWidgets import QInputDialog
+
+from eric7 import Preferences
+from eric7.EricWidgets import EricMessageBox
+from eric7.EricWidgets.EricApplication import ericApp
+
+
+class BaseDevice(QObject):
+    """
+    Base class for the more specific MicroPython devices.
+    """
+
+    def __init__(self, microPythonWidget, deviceType, parent=None):
+        """
+        Constructor
+
+        @param microPythonWidget reference to the main MicroPython widget
+        @type MicroPythonWidget
+        @param deviceType device type assigned to this device interface
+        @type str
+        @param parent reference to the parent object
+        @type QObject
+        """
+        super().__init__(parent)
+
+        self._deviceType = deviceType
+        self.microPython = microPythonWidget
+        self._deviceData = {}  # dictionary with essential device data
+
+    def setConnected(self, connected):
+        """
+        Public method to set the connection state.
+
+        Note: This method can be overwritten to perform actions upon connect
+        or disconnect of the device.
+
+        @param connected connection state
+        @type bool
+        """
+        self._deviceData = {}
+
+        if connected:
+            with contextlib.suppress(OSError):
+                self._deviceData = self.microPython.commandsInterface().getDeviceData()
+
+    def getDeviceType(self):
+        """
+        Public method to get the device type.
+
+        @return type of the device
+        @rtype str
+        """
+        return self._deviceType
+
+    def getDeviceData(self):
+        """
+        Public method to get a copy of the determined device data.
+
+        @return dictionary containing the essential device data
+        @rtype dict
+        """
+        return copy.deepcopy(self._deviceData)
+
+    def checkDeviceData(self):
+        """
+        Public method to check the validity of the device data determined during
+        connecting the device.
+
+        @return flag indicating valid device data
+        @rtype bool
+        """
+        if bool(self._deviceData):
+            return True
+        else:
+            EricMessageBox.critical(
+                None,
+                self.tr("Show MicroPython Versions"),
+                self.tr(
+                    """<p>The device data is not available. Try to connect to the"""
+                    """ device again. Aborting...</p>"""
+                ).format(self.getDeviceType()),
+            )
+            return False
+
+    def setButtons(self):
+        """
+        Public method to enable the supported action buttons.
+        """
+        self.microPython.setActionButtons(
+            open=False, save=False, run=False, repl=False, files=False, chart=False
+        )
+
+    def forceInterrupt(self):
+        """
+        Public method to determine the need for an interrupt when opening the
+        serial connection.
+
+        @return flag indicating an interrupt is needed
+        @rtype bool
+        """
+        return True
+
+    def deviceName(self):
+        """
+        Public method to get the name of the device.
+
+        @return name of the device
+        @rtype str
+        """
+        return self.tr("Unsupported Device")
+
+    def canStartRepl(self):
+        """
+        Public method to determine, if a REPL can be started.
+
+        @return tuple containing a flag indicating it is safe to start a REPL
+            and a reason why it cannot.
+        @rtype tuple of (bool, str)
+        """
+        return False, self.tr("REPL is not supported by this device.")
+
+    def setRepl(self, on):
+        """
+        Public method to set the REPL status and dependent status.
+
+        @param on flag indicating the active status
+        @type bool
+        """
+        pass
+
+    def canStartPlotter(self):
+        """
+        Public method to determine, if a Plotter can be started.
+
+        @return tuple containing a flag indicating it is safe to start a
+            Plotter and a reason why it cannot.
+        @rtype tuple of (bool, str)
+        """
+        return False, self.tr("Plotter is not supported by this device.")
+
+    def setPlotter(self, on):
+        """
+        Public method to set the Plotter status and dependent status.
+
+        @param on flag indicating the active status
+        @type bool
+        """
+        pass
+
+    def canRunScript(self):
+        """
+        Public method to determine, if a script can be executed.
+
+        @return tuple containing a flag indicating it is safe to start a
+            Plotter and a reason why it cannot.
+        @rtype tuple of (bool, str)
+        """
+        return False, self.tr("Running scripts is not supported by this device.")
+
+    def runScript(self, script):
+        """
+        Public method to run the given Python script.
+
+        @param script script to be executed
+        @type str
+        """
+        pass
+
+    def canStartFileManager(self):
+        """
+        Public method to determine, if a File Manager can be started.
+
+        @return tuple containing a flag indicating it is safe to start a
+            File Manager and a reason why it cannot.
+        @rtype tuple of (bool, str)
+        """
+        return False, self.tr("File Manager is not supported by this device.")
+
+    def setFileManager(self, on):
+        """
+        Public method to set the File Manager status and dependent status.
+
+        @param on flag indicating the active status
+        @type bool
+        """
+        pass
+
+    def supportsLocalFileAccess(self):
+        """
+        Public method to indicate file access via a local directory.
+
+        @return flag indicating file access via local directory
+        @rtype bool
+        """
+        return False  # default
+
+    def getWorkspace(self):
+        """
+        Public method to get the workspace directory.
+
+        @return workspace directory used for saving files
+        @rtype str
+        """
+        return (
+            Preferences.getMicroPython("MpyWorkspace")
+            or Preferences.getMultiProject("Workspace")
+            or os.path.expanduser("~")
+        )
+
+    def selectDeviceDirectory(self, deviceDirectories):
+        """
+        Public method to select the device directory from a list of detected
+        ones.
+
+        @param deviceDirectories list of directories to select from
+        @type list of str
+        @return selected directory or an empty string
+        @rtype str
+        """
+        deviceDirectory, ok = QInputDialog.getItem(
+            None,
+            self.tr("Select Device Directory"),
+            self.tr("Select the directory for the connected device:"),
+            [""] + deviceDirectories,
+            0,
+            False,
+        )
+        if ok:
+            return deviceDirectory
+        else:
+            # user cancelled
+            return ""
+
+    def sendCommands(self, commandsList):
+        """
+        Public method to send a list of commands to the device.
+
+        @param commandsList list of commands to be sent to the device
+        @type list of str
+        """
+        rawOn = [  # sequence of commands to enter raw mode
+            b"\x02",  # Ctrl-B: exit raw repl (just in case)
+            b"\r\x03\x03\x03",  # Ctrl-C three times: interrupt any running
+            # program
+            b"\r\x01",  # Ctrl-A: enter raw REPL
+        ]
+        newLine = [
+            b'print("\\n")\r',
+        ]
+        commands = [c.encode("utf-8)") + b"\r" for c in commandsList]
+        commands.append(b"\r")
+        commands.append(b"\x04")
+        rawOff = [b"\x02", b"\x02"]
+        commandSequence = rawOn + newLine + commands + rawOff
+        self.microPython.commandsInterface().executeAsync(commandSequence)
+
+    @pyqtSlot()
+    def handleDataFlood(self):
+        """
+        Public slot handling a data floof from the device.
+        """
+        pass
+
+    def addDeviceMenuEntries(self, menu):
+        """
+        Public method to add device specific entries to the given menu.
+
+        @param menu reference to the context menu
+        @type QMenu
+        """
+        pass
+
+    def hasFlashMenuEntry(self):
+        """
+        Public method to check, if the device has its own flash menu entry.
+
+        @return flag indicating a specific flash menu entry
+        @rtype bool
+        """
+        return False
+
+    def hasTimeCommands(self):
+        """
+        Public method to check, if the device supports time commands.
+
+        The default returns True.
+
+        @return flag indicating support for time commands
+        @rtype bool
+        """
+        return True
+
+    def hasDocumentationUrl(self):
+        """
+        Public method to check, if the device has a configured documentation
+        URL.
+
+        @return flag indicating a configured documentation URL
+        @rtype bool
+        """
+        return bool(self.getDocumentationUrl())
+
+    def getDocumentationUrl(self):
+        """
+        Public method to get the device documentation URL.
+
+        @return documentation URL of the device
+        @rtype str
+        """
+        return ""
+
+    def hasFirmwareUrl(self):
+        """
+        Public method to check, if the device has a configured firmware
+        download URL.
+
+        @return flag indicating a configured firmware download URL
+        @rtype bool
+        """
+        return bool(self.getFirmwareUrl())
+
+    def getFirmwareUrl(self):
+        """
+        Public method to get the device firmware download URL.
+
+        @return firmware download URL of the device
+        @rtype str
+        """
+        return ""
+
+    def downloadFirmware(self):
+        """
+        Public method to download the device firmware.
+        """
+        url = self.getFirmwareUrl()
+        if url:
+            ericApp().getObject("UserInterface").launchHelpViewer(url)
+
+    def getDownloadMenuEntries(self):
+        """
+        Public method to retrieve the entries for the downloads menu.
+
+        @return list of tuples with menu text and URL to be opened for each
+            entry
+        @rtype list of tuple of (str, str)
+        """
+        return []

eric ide

mercurial