MicroPython mpy_network

Fri, 28 Apr 2023 12:07:41 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 28 Apr 2023 12:07:41 +0200
branch
mpy_network
changeset 9990
54c614d91eff
parent 9989
286c2a21f36f
child 10008
c5bcafe3485c

MicroPython
- Refactored the code by introducing a device interface base class and changed the interface instantiation logic to prepare the basis for developing the 'webrepl' interface.

Dictionaries/words.dic file | annotate | diff | comparison | revisions
eric7.epj file | annotate | diff | comparison | revisions
src/eric7/APIs/Python3/eric7.api file | annotate | diff | comparison | revisions
src/eric7/APIs/Python3/eric7.bas file | annotate | diff | comparison | revisions
src/eric7/Documentation/Help/source.qch file | annotate | diff | comparison | revisions
src/eric7/Documentation/Help/source.qhp file | annotate | diff | comparison | revisions
src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonDeviceInterface.html file | annotate | diff | comparison | revisions
src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonSerialDeviceInterface.html file | annotate | diff | comparison | revisions
src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonWidget.html file | annotate | diff | comparison | revisions
src/eric7/Documentation/Source/index-eric7.MicroPython.html file | annotate | diff | comparison | revisions
src/eric7/MicroPython/MicroPythonDeviceInterface.py file | annotate | diff | comparison | revisions
src/eric7/MicroPython/MicroPythonSerialDeviceInterface.py file | annotate | diff | comparison | revisions
src/eric7/MicroPython/MicroPythonWidget.py file | annotate | diff | comparison | revisions
--- a/Dictionaries/words.dic	Thu Apr 27 17:59:09 2023 +0200
+++ b/Dictionaries/words.dic	Fri Apr 28 12:07:41 2023 +0200
@@ -8,3 +8,4 @@
 param
 keyparam
 rtype
+instantiation
--- a/eric7.epj	Thu Apr 27 17:59:09 2023 +0200
+++ b/eric7.epj	Fri Apr 28 12:07:41 2023 +0200
@@ -1347,6 +1347,7 @@
       "src/eric7/MicroPython/MicroPythonFileSystemUtilities.py",
       "src/eric7/MicroPython/MicroPythonGraphWidget.py",
       "src/eric7/MicroPython/MicroPythonProgressInfoDialog.py",
+      "src/eric7/MicroPython/MicroPythonSerialDeviceInterface.py",
       "src/eric7/MicroPython/MicroPythonSerialPort.py",
       "src/eric7/MicroPython/MicroPythonWidget.py",
       "src/eric7/MicroPython/MipLocalInstaller.py",
--- a/src/eric7/APIs/Python3/eric7.api	Thu Apr 27 17:59:09 2023 +0200
+++ b/src/eric7/APIs/Python3/eric7.api	Fri Apr 28 12:07:41 2023 +0200
@@ -2955,9 +2955,7 @@
 eric7.MicroPython.EthernetDialogs.WiznetUtilities.mpyWiznetInit?4()
 eric7.MicroPython.IgnoredDevicesDialog.IgnoredDevicesDialog.getDevices?4()
 eric7.MicroPython.IgnoredDevicesDialog.IgnoredDevicesDialog?1(deviceList, parent=None)
-eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.PasteModePrompt?7
-eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.TracebackMarker?7
-eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.connectToDevice?4(port)
+eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.connectToDevice?4(connection)
 eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.dataReceived?7
 eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.disconnectFromDevice?4()
 eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.execute?4(commands, *, mode="raw", timeout=0)
@@ -3037,6 +3035,17 @@
 eric7.MicroPython.MicroPythonGraphWidget.MicroPythonGraphWidget?1(parent=None)
 eric7.MicroPython.MicroPythonProgressInfoDialog.MicroPythonProgressInfoDialog.addMessage?4(message)
 eric7.MicroPython.MicroPythonProgressInfoDialog.MicroPythonProgressInfoDialog?1(parent=None)
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.PasteModePrompt?7
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.TracebackMarker?7
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.connectToDevice?4(connection)
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.disconnectFromDevice?4()
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.execute?4(commands, *, mode="raw", timeout=0)
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.executeAsync?4(commandsList, submitMode)
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.handlePreferencesChanged?4()
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.isConnected?4()
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.probeDevice?4()
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface.write?4(data)
+eric7.MicroPython.MicroPythonSerialDeviceInterface.MicroPythonSerialDeviceInterface?1(parent=None)
 eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort.closeSerialLink?4()
 eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort.hasTimedOut?4()
 eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort.isConnected?4()
@@ -3046,6 +3055,7 @@
 eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort?1(timeout=10000, parent=None)
 eric7.MicroPython.MicroPythonWidget.AnsiColorSchemes?7
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.DeviceBoardRole?7
+eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.DeviceInterfaceTypeRole?7
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.DevicePidRole?7
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.DevicePortRole?7
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.DeviceSerNoRole?7
@@ -3058,7 +3068,6 @@
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.deviceInterface?4()
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.deviceSupportsLocalFileAccess?4()
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.eventFilter?4(obj, evt)
-eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.getCurrentBoard?4()
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.getCurrentPort?4()
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.getDevice?4()
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.getDeviceWorkspace?4()
--- a/src/eric7/APIs/Python3/eric7.bas	Thu Apr 27 17:59:09 2023 +0200
+++ b/src/eric7/APIs/Python3/eric7.bas	Fri Apr 28 12:07:41 2023 +0200
@@ -664,6 +664,7 @@
 MicroPythonGraphWidget QWidget
 MicroPythonPage ConfigurationPageBase Ui_MicroPythonPage
 MicroPythonProgressInfoDialog QDialog Ui_MicroPythonProgressInfoDialog
+MicroPythonSerialDeviceInterface MicroPythonDeviceInterface
 MicroPythonSerialPort QSerialPort
 MicroPythonWidget QWidget Ui_MicroPythonWidget
 MicrobitDevice BaseDevice
Binary file src/eric7/Documentation/Help/source.qch has changed
--- a/src/eric7/Documentation/Help/source.qhp	Thu Apr 27 17:59:09 2023 +0200
+++ b/src/eric7/Documentation/Help/source.qhp	Fri Apr 28 12:07:41 2023 +0200
@@ -327,6 +327,7 @@
             <section title="eric7.MicroPython.MicroPythonFileSystemUtilities" ref="eric7.MicroPython.MicroPythonFileSystemUtilities.html" />
             <section title="eric7.MicroPython.MicroPythonGraphWidget" ref="eric7.MicroPython.MicroPythonGraphWidget.html" />
             <section title="eric7.MicroPython.MicroPythonProgressInfoDialog" ref="eric7.MicroPython.MicroPythonProgressInfoDialog.html" />
+            <section title="eric7.MicroPython.MicroPythonSerialDeviceInterface" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html" />
             <section title="eric7.MicroPython.MicroPythonSerialPort" ref="eric7.MicroPython.MicroPythonSerialPort.html" />
             <section title="eric7.MicroPython.MicroPythonWidget" ref="eric7.MicroPython.MicroPythonWidget.html" />
             <section title="eric7.MicroPython.MipLocalInstaller" ref="eric7.MicroPython.MipLocalInstaller.html" />
@@ -10793,15 +10794,6 @@
       <keyword name="MicroPythonDeviceInterface" id="MicroPythonDeviceInterface" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface" />
       <keyword name="MicroPythonDeviceInterface (Constructor)" id="MicroPythonDeviceInterface (Constructor)" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__init__" />
       <keyword name="MicroPythonDeviceInterface (Module)" id="MicroPythonDeviceInterface (Module)" ref="eric7.MicroPython.MicroPythonDeviceInterface.html" />
-      <keyword name="MicroPythonDeviceInterface.__executeAsyncPaste" id="MicroPythonDeviceInterface.__executeAsyncPaste" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__executeAsyncPaste" />
-      <keyword name="MicroPythonDeviceInterface.__executeAsyncRaw" id="MicroPythonDeviceInterface.__executeAsyncRaw" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__executeAsyncRaw" />
-      <keyword name="MicroPythonDeviceInterface.__execute_paste" id="MicroPythonDeviceInterface.__execute_paste" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__execute_paste" />
-      <keyword name="MicroPythonDeviceInterface.__execute_raw" id="MicroPythonDeviceInterface.__execute_raw" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__execute_raw" />
-      <keyword name="MicroPythonDeviceInterface.__pasteOff" id="MicroPythonDeviceInterface.__pasteOff" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__pasteOff" />
-      <keyword name="MicroPythonDeviceInterface.__pasteOn" id="MicroPythonDeviceInterface.__pasteOn" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__pasteOn" />
-      <keyword name="MicroPythonDeviceInterface.__rawOff" id="MicroPythonDeviceInterface.__rawOff" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__rawOff" />
-      <keyword name="MicroPythonDeviceInterface.__rawOn" id="MicroPythonDeviceInterface.__rawOn" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__rawOn" />
-      <keyword name="MicroPythonDeviceInterface.__readSerial" id="MicroPythonDeviceInterface.__readSerial" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.__readSerial" />
       <keyword name="MicroPythonDeviceInterface.connectToDevice" id="MicroPythonDeviceInterface.connectToDevice" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.connectToDevice" />
       <keyword name="MicroPythonDeviceInterface.disconnectFromDevice" id="MicroPythonDeviceInterface.disconnectFromDevice" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.disconnectFromDevice" />
       <keyword name="MicroPythonDeviceInterface.execute" id="MicroPythonDeviceInterface.execute" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.execute" />
@@ -10903,6 +10895,26 @@
       <keyword name="MicroPythonProgressInfoDialog (Constructor)" id="MicroPythonProgressInfoDialog (Constructor)" ref="eric7.MicroPython.MicroPythonProgressInfoDialog.html#MicroPythonProgressInfoDialog.__init__" />
       <keyword name="MicroPythonProgressInfoDialog (Module)" id="MicroPythonProgressInfoDialog (Module)" ref="eric7.MicroPython.MicroPythonProgressInfoDialog.html" />
       <keyword name="MicroPythonProgressInfoDialog.addMessage" id="MicroPythonProgressInfoDialog.addMessage" ref="eric7.MicroPython.MicroPythonProgressInfoDialog.html#MicroPythonProgressInfoDialog.addMessage" />
+      <keyword name="MicroPythonSerialDeviceInterface" id="MicroPythonSerialDeviceInterface" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface" />
+      <keyword name="MicroPythonSerialDeviceInterface (Constructor)" id="MicroPythonSerialDeviceInterface (Constructor)" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__init__" />
+      <keyword name="MicroPythonSerialDeviceInterface (Module)" id="MicroPythonSerialDeviceInterface (Module)" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html" />
+      <keyword name="MicroPythonSerialDeviceInterface.__executeAsyncPaste" id="MicroPythonSerialDeviceInterface.__executeAsyncPaste" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__executeAsyncPaste" />
+      <keyword name="MicroPythonSerialDeviceInterface.__executeAsyncRaw" id="MicroPythonSerialDeviceInterface.__executeAsyncRaw" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__executeAsyncRaw" />
+      <keyword name="MicroPythonSerialDeviceInterface.__execute_paste" id="MicroPythonSerialDeviceInterface.__execute_paste" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__execute_paste" />
+      <keyword name="MicroPythonSerialDeviceInterface.__execute_raw" id="MicroPythonSerialDeviceInterface.__execute_raw" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__execute_raw" />
+      <keyword name="MicroPythonSerialDeviceInterface.__pasteOff" id="MicroPythonSerialDeviceInterface.__pasteOff" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__pasteOff" />
+      <keyword name="MicroPythonSerialDeviceInterface.__pasteOn" id="MicroPythonSerialDeviceInterface.__pasteOn" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__pasteOn" />
+      <keyword name="MicroPythonSerialDeviceInterface.__rawOff" id="MicroPythonSerialDeviceInterface.__rawOff" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__rawOff" />
+      <keyword name="MicroPythonSerialDeviceInterface.__rawOn" id="MicroPythonSerialDeviceInterface.__rawOn" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__rawOn" />
+      <keyword name="MicroPythonSerialDeviceInterface.__readSerial" id="MicroPythonSerialDeviceInterface.__readSerial" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.__readSerial" />
+      <keyword name="MicroPythonSerialDeviceInterface.connectToDevice" id="MicroPythonSerialDeviceInterface.connectToDevice" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.connectToDevice" />
+      <keyword name="MicroPythonSerialDeviceInterface.disconnectFromDevice" id="MicroPythonSerialDeviceInterface.disconnectFromDevice" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.disconnectFromDevice" />
+      <keyword name="MicroPythonSerialDeviceInterface.execute" id="MicroPythonSerialDeviceInterface.execute" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.execute" />
+      <keyword name="MicroPythonSerialDeviceInterface.executeAsync" id="MicroPythonSerialDeviceInterface.executeAsync" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.executeAsync" />
+      <keyword name="MicroPythonSerialDeviceInterface.handlePreferencesChanged" id="MicroPythonSerialDeviceInterface.handlePreferencesChanged" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.handlePreferencesChanged" />
+      <keyword name="MicroPythonSerialDeviceInterface.isConnected" id="MicroPythonSerialDeviceInterface.isConnected" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.isConnected" />
+      <keyword name="MicroPythonSerialDeviceInterface.probeDevice" id="MicroPythonSerialDeviceInterface.probeDevice" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.probeDevice" />
+      <keyword name="MicroPythonSerialDeviceInterface.write" id="MicroPythonSerialDeviceInterface.write" ref="eric7.MicroPython.MicroPythonSerialDeviceInterface.html#MicroPythonSerialDeviceInterface.write" />
       <keyword name="MicroPythonSerialPort" id="MicroPythonSerialPort" ref="eric7.MicroPython.MicroPythonSerialPort.html#MicroPythonSerialPort" />
       <keyword name="MicroPythonSerialPort (Constructor)" id="MicroPythonSerialPort (Constructor)" ref="eric7.MicroPython.MicroPythonSerialPort.html#MicroPythonSerialPort.__init__" />
       <keyword name="MicroPythonSerialPort (Module)" id="MicroPythonSerialPort (Module)" ref="eric7.MicroPython.MicroPythonSerialPort.html" />
@@ -10955,7 +10967,6 @@
       <keyword name="MicroPythonWidget.deviceInterface" id="MicroPythonWidget.deviceInterface" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.deviceInterface" />
       <keyword name="MicroPythonWidget.deviceSupportsLocalFileAccess" id="MicroPythonWidget.deviceSupportsLocalFileAccess" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.deviceSupportsLocalFileAccess" />
       <keyword name="MicroPythonWidget.eventFilter" id="MicroPythonWidget.eventFilter" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.eventFilter" />
-      <keyword name="MicroPythonWidget.getCurrentBoard" id="MicroPythonWidget.getCurrentBoard" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.getCurrentBoard" />
       <keyword name="MicroPythonWidget.getCurrentPort" id="MicroPythonWidget.getCurrentPort" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.getCurrentPort" />
       <keyword name="MicroPythonWidget.getDevice" id="MicroPythonWidget.getDevice" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.getDevice" />
       <keyword name="MicroPythonWidget.getDeviceWorkspace" id="MicroPythonWidget.getDeviceWorkspace" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.getDeviceWorkspace" />
@@ -20569,6 +20580,7 @@
       <file>eric7.MicroPython.MicroPythonFileSystemUtilities.html</file>
       <file>eric7.MicroPython.MicroPythonGraphWidget.html</file>
       <file>eric7.MicroPython.MicroPythonProgressInfoDialog.html</file>
+      <file>eric7.MicroPython.MicroPythonSerialDeviceInterface.html</file>
       <file>eric7.MicroPython.MicroPythonSerialPort.html</file>
       <file>eric7.MicroPython.MicroPythonWidget.html</file>
       <file>eric7.MicroPython.MipLocalInstaller.html</file>
--- a/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonDeviceInterface.html	Thu Apr 27 17:59:09 2023 +0200
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonDeviceInterface.html	Fri Apr 28 12:07:41 2023 +0200
@@ -9,7 +9,7 @@
 <h1>eric7.MicroPython.MicroPythonDeviceInterface</h1>
 
 <p>
-Module implementing some file system commands for MicroPython.
+Module  implementing an interface base class to talk to a connected MicroPython device.
 </p>
 <h3>Global Attributes</h3>
 
@@ -43,8 +43,8 @@
 
 <dt>dataReceived(data)</dt>
 <dd>
-emitted to send data received via the serial
-        connection for further processing
+emitted to send data received via the connection
+        for further processing
 </dd>
 <dt>executeAsyncFinished()</dt>
 <dd>
@@ -57,7 +57,7 @@
 <h3>Class Attributes</h3>
 
 <table>
-<tr><td>PasteModePrompt</td></tr><tr><td>TracebackMarker</td></tr>
+<tr><td>None</td></tr>
 </table>
 <h3>Class Methods</h3>
 
@@ -73,48 +73,12 @@
 <td>Constructor</td>
 </tr>
 <tr>
-<td><a href="#MicroPythonDeviceInterface.__executeAsyncPaste">__executeAsyncPaste</a></td>
-<td>Private method to execute a series of commands over a period of time without returning any result (asynchronous execution).</td>
-</tr>
-<tr>
-<td><a href="#MicroPythonDeviceInterface.__executeAsyncRaw">__executeAsyncRaw</a></td>
-<td>Private method to execute a series of commands over a period of time without returning any result (asynchronous execution).</td>
-</tr>
-<tr>
-<td><a href="#MicroPythonDeviceInterface.__execute_paste">__execute_paste</a></td>
-<td>Private method to send commands to the connected device using 'paste' mode and return the result.</td>
-</tr>
-<tr>
-<td><a href="#MicroPythonDeviceInterface.__execute_raw">__execute_raw</a></td>
-<td>Private method to send commands to the connected device using 'raw REPL' mode and return the result.</td>
-</tr>
-<tr>
-<td><a href="#MicroPythonDeviceInterface.__pasteOff">__pasteOff</a></td>
-<td>Private method to switch 'paste' mode off.</td>
-</tr>
-<tr>
-<td><a href="#MicroPythonDeviceInterface.__pasteOn">__pasteOn</a></td>
-<td>Private method to switch the connected device to 'paste' mode.</td>
-</tr>
-<tr>
-<td><a href="#MicroPythonDeviceInterface.__rawOff">__rawOff</a></td>
-<td>Private method to switch 'raw' mode off.</td>
-</tr>
-<tr>
-<td><a href="#MicroPythonDeviceInterface.__rawOn">__rawOn</a></td>
-<td>Private method to switch the connected device to 'raw' mode.</td>
-</tr>
-<tr>
-<td><a href="#MicroPythonDeviceInterface.__readSerial">__readSerial</a></td>
-<td>Private slot to read all available serial data and emit it with the "dataReceived" signal for further processing.</td>
-</tr>
-<tr>
 <td><a href="#MicroPythonDeviceInterface.connectToDevice">connectToDevice</a></td>
-<td>Public slot to start the manager.</td>
+<td>Public slot to connect to the device.</td>
 </tr>
 <tr>
 <td><a href="#MicroPythonDeviceInterface.disconnectFromDevice">disconnectFromDevice</a></td>
-<td>Public slot to stop the thread.</td>
+<td>Public slot to disconnect from the device.</td>
 </tr>
 <tr>
 <td><a href="#MicroPythonDeviceInterface.execute">execute</a></td>
@@ -161,184 +125,18 @@
 reference to the parent object
 </dd>
 </dl>
-<a NAME="MicroPythonDeviceInterface.__executeAsyncPaste" ID="MicroPythonDeviceInterface.__executeAsyncPaste"></a>
-<h4>MicroPythonDeviceInterface.__executeAsyncPaste</h4>
-<b>__executeAsyncPaste</b>(<i>commandsList</i>)
-
-<p>
-        Private method to execute a series of commands over a period of time
-        without returning any result (asynchronous execution).
-</p>
-<dl>
-
-<dt><i>commandsList</i> (list of str)</dt>
-<dd>
-list of commands to be execute on the device
-</dd>
-</dl>
-<a NAME="MicroPythonDeviceInterface.__executeAsyncRaw" ID="MicroPythonDeviceInterface.__executeAsyncRaw"></a>
-<h4>MicroPythonDeviceInterface.__executeAsyncRaw</h4>
-<b>__executeAsyncRaw</b>(<i>commandsList</i>)
-
-<p>
-        Private method to execute a series of commands over a period of time
-        without returning any result (asynchronous execution).
-</p>
-<dl>
-
-<dt><i>commandsList</i> (list of bytes)</dt>
-<dd>
-list of commands to be execute on the device
-</dd>
-</dl>
-<a NAME="MicroPythonDeviceInterface.__execute_paste" ID="MicroPythonDeviceInterface.__execute_paste"></a>
-<h4>MicroPythonDeviceInterface.__execute_paste</h4>
-<b>__execute_paste</b>(<i>commands, timeout=0</i>)
+<a NAME="MicroPythonDeviceInterface.connectToDevice" ID="MicroPythonDeviceInterface.connectToDevice"></a>
+<h4>MicroPythonDeviceInterface.connectToDevice</h4>
+<b>connectToDevice</b>(<i>connection</i>)
 
 <p>
-        Private method to send commands to the connected device using 'paste' mode
-        and return the result.
-</p>
-<p>
-        If no serial connection is available, empty results will be returned.
-</p>
-<dl>
-
-<dt><i>commands</i> (str or list of str)</dt>
-<dd>
-list of commands to be executed
-</dd>
-<dt><i>timeout</i> (int (optional))</dt>
-<dd>
-per command timeout in milliseconds (0 for configured default)
-            (defaults to 0)
-</dd>
-</dl>
-<dl>
-<dt>Return:</dt>
-<dd>
-tuple containing stdout and stderr output of the device
-</dd>
-</dl>
-<dl>
-<dt>Return Type:</dt>
-<dd>
-tuple of (bytes, bytes)
-</dd>
-</dl>
-<a NAME="MicroPythonDeviceInterface.__execute_raw" ID="MicroPythonDeviceInterface.__execute_raw"></a>
-<h4>MicroPythonDeviceInterface.__execute_raw</h4>
-<b>__execute_raw</b>(<i>commands, timeout=0</i>)
-
-<p>
-        Private method to send commands to the connected device using 'raw REPL' mode
-        and return the result.
-</p>
-<p>
-        If no serial connection is available, empty results will be returned.
+        Public slot to connect to the device.
 </p>
 <dl>
 
-<dt><i>commands</i> (str or list of str)</dt>
-<dd>
-list of commands to be executed
-</dd>
-<dt><i>timeout</i> (int (optional))</dt>
-<dd>
-per command timeout in milliseconds (0 for configured default)
-            (defaults to 0)
-</dd>
-</dl>
-<dl>
-<dt>Return:</dt>
-<dd>
-tuple containing stdout and stderr output of the device
-</dd>
-</dl>
-<dl>
-<dt>Return Type:</dt>
-<dd>
-tuple of (bytes, bytes)
-</dd>
-</dl>
-<a NAME="MicroPythonDeviceInterface.__pasteOff" ID="MicroPythonDeviceInterface.__pasteOff"></a>
-<h4>MicroPythonDeviceInterface.__pasteOff</h4>
-<b>__pasteOff</b>(<i></i>)
-
-<p>
-        Private method to switch 'paste' mode off.
-</p>
-<a NAME="MicroPythonDeviceInterface.__pasteOn" ID="MicroPythonDeviceInterface.__pasteOn"></a>
-<h4>MicroPythonDeviceInterface.__pasteOn</h4>
-<b>__pasteOn</b>(<i></i>)
-
-<p>
-        Private method to switch the connected device to 'paste' mode.
-</p>
-<p>
-        Note: switching to paste mode is done with synchronous writes.
-</p>
-<dl>
-<dt>Return:</dt>
-<dd>
-flag indicating success
-</dd>
-</dl>
-<dl>
-<dt>Return Type:</dt>
+<dt><i>connection</i> (str)</dt>
 <dd>
-bool
-</dd>
-</dl>
-<a NAME="MicroPythonDeviceInterface.__rawOff" ID="MicroPythonDeviceInterface.__rawOff"></a>
-<h4>MicroPythonDeviceInterface.__rawOff</h4>
-<b>__rawOff</b>(<i></i>)
-
-<p>
-        Private method to switch 'raw' mode off.
-</p>
-<a NAME="MicroPythonDeviceInterface.__rawOn" ID="MicroPythonDeviceInterface.__rawOn"></a>
-<h4>MicroPythonDeviceInterface.__rawOn</h4>
-<b>__rawOn</b>(<i></i>)
-
-<p>
-        Private method to switch the connected device to 'raw' mode.
-</p>
-<p>
-        Note: switching to raw mode is done with synchronous writes.
-</p>
-<dl>
-<dt>Return:</dt>
-<dd>
-flag indicating success
-</dd>
-</dl>
-<dl>
-<dt>Return Type:</dt>
-<dd>
-bool
-</dd>
-</dl>
-<a NAME="MicroPythonDeviceInterface.__readSerial" ID="MicroPythonDeviceInterface.__readSerial"></a>
-<h4>MicroPythonDeviceInterface.__readSerial</h4>
-<b>__readSerial</b>(<i></i>)
-
-<p>
-        Private slot to read all available serial data and emit it with the
-        "dataReceived" signal for further processing.
-</p>
-<a NAME="MicroPythonDeviceInterface.connectToDevice" ID="MicroPythonDeviceInterface.connectToDevice"></a>
-<h4>MicroPythonDeviceInterface.connectToDevice</h4>
-<b>connectToDevice</b>(<i>port</i>)
-
-<p>
-        Public slot to start the manager.
-</p>
-<dl>
-
-<dt><i>port</i> (str)</dt>
-<dd>
-name of the port to be used
+name of the connection to be used
 </dd>
 </dl>
 <dl>
@@ -353,13 +151,29 @@
 bool
 </dd>
 </dl>
+<dl>
+
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+raised to indicate that this method needs to
+            be implemented in a derived class
+</dd>
+</dl>
 <a NAME="MicroPythonDeviceInterface.disconnectFromDevice" ID="MicroPythonDeviceInterface.disconnectFromDevice"></a>
 <h4>MicroPythonDeviceInterface.disconnectFromDevice</h4>
 <b>disconnectFromDevice</b>(<i></i>)
 
 <p>
-        Public slot to stop the thread.
+        Public slot to disconnect from the device.
 </p>
+<dl>
+
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+raised to indicate that this method needs to
+            be implemented in a derived class
+</dd>
+</dl>
 <a NAME="MicroPythonDeviceInterface.execute" ID="MicroPythonDeviceInterface.execute"></a>
 <h4>MicroPythonDeviceInterface.execute</h4>
 <b>execute</b>(<i>commands, *, mode="raw", timeout=0</i>)
@@ -369,7 +183,7 @@
         result.
 </p>
 <p>
-        If no serial connection is available, empty results will be returned.
+        If no connection is available, empty results will be returned.
 </p>
 <dl>
 
@@ -402,6 +216,11 @@
 </dl>
 <dl>
 
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+raised to indicate that this method needs to
+            be implemented in a derived class
+</dd>
 <dt>Raises <b>ValueError</b>:</dt>
 <dd>
 raised in case of an unsupported submit mode
@@ -421,13 +240,19 @@
 <dd>
 list of commands to be execute on the device
 </dd>
-<dt><i>submitMode</i> (str (one of 'raw' or 'paste'))</dt>
+<dt><i>submitMode</i> (str)</dt>
 <dd>
-mode to be used to submit the commands
+mode to be used to submit the commands (one of 'raw'
+            or 'paste')
 </dd>
 </dl>
 <dl>
 
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+raised to indicate that this method needs to
+            be implemented in a derived class
+</dd>
 <dt>Raises <b>ValueError</b>:</dt>
 <dd>
 raised to indicate an unknown submit mode
@@ -459,6 +284,14 @@
 bool
 </dd>
 </dl>
+<dl>
+
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+raised to indicate that this method needs to
+            be implemented in a derived class
+</dd>
+</dl>
 <a NAME="MicroPythonDeviceInterface.probeDevice" ID="MicroPythonDeviceInterface.probeDevice"></a>
 <h4>MicroPythonDeviceInterface.probeDevice</h4>
 <b>probeDevice</b>(<i></i>)
@@ -467,7 +300,7 @@
         Public method to check the device is responding.
 </p>
 <p>
-        If the device has not been flashed with a MicroPython formware, the
+        If the device has not been flashed with a MicroPython firmware, the
         probe will fail.
 </p>
 <dl>
@@ -482,6 +315,14 @@
 bool
 </dd>
 </dl>
+<dl>
+
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+raised to indicate that this method needs to
+            be implemented in a derived class
+</dd>
+</dl>
 <a NAME="MicroPythonDeviceInterface.write" ID="MicroPythonDeviceInterface.write"></a>
 <h4>MicroPythonDeviceInterface.write</h4>
 <b>write</b>(<i>data</i>)
@@ -496,6 +337,14 @@
 data to be written
 </dd>
 </dl>
+<dl>
+
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+raised to indicate that this method needs to
+            be implemented in a derived class
+</dd>
+</dl>
 <div align="right"><a href="#top">Up</a></div>
 <hr />
 </body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonSerialDeviceInterface.html	Fri Apr 28 12:07:41 2023 +0200
@@ -0,0 +1,489 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.MicroPythonSerialDeviceInterface</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.MicroPythonSerialDeviceInterface</h1>
+
+<p>
+Module  implementing an interface to talk to a connected MicroPython device via
+a serial link.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface">MicroPythonSerialDeviceInterface</a></td>
+<td>Class implementing an interface to talk to a connected MicroPython device via a serial link.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="MicroPythonSerialDeviceInterface" ID="MicroPythonSerialDeviceInterface"></a>
+<h2>MicroPythonSerialDeviceInterface</h2>
+
+<p>
+    Class implementing an interface to talk to a connected MicroPython device via
+    a serial link.
+</p>
+<h3>Derived from</h3>
+MicroPythonDeviceInterface
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>PasteModePrompt</td></tr><tr><td>TracebackMarker</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__init__">MicroPythonSerialDeviceInterface</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__executeAsyncPaste">__executeAsyncPaste</a></td>
+<td>Private method to execute a series of commands over a period of time without returning any result (asynchronous execution).</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__executeAsyncRaw">__executeAsyncRaw</a></td>
+<td>Private method to execute a series of commands over a period of time without returning any result (asynchronous execution).</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__execute_paste">__execute_paste</a></td>
+<td>Private method to send commands to the connected device using 'paste' mode and return the result.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__execute_raw">__execute_raw</a></td>
+<td>Private method to send commands to the connected device using 'raw REPL' mode and return the result.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__pasteOff">__pasteOff</a></td>
+<td>Private method to switch 'paste' mode off.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__pasteOn">__pasteOn</a></td>
+<td>Private method to switch the connected device to 'paste' mode.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__rawOff">__rawOff</a></td>
+<td>Private method to switch 'raw' mode off.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__rawOn">__rawOn</a></td>
+<td>Private method to switch the connected device to 'raw' mode.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.__readSerial">__readSerial</a></td>
+<td>Private slot to read all available serial data and emit it with the "dataReceived" signal for further processing.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.connectToDevice">connectToDevice</a></td>
+<td>Public slot to connect to the device.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.disconnectFromDevice">disconnectFromDevice</a></td>
+<td>Public slot to disconnect from the device.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.execute">execute</a></td>
+<td>Public method to send commands to the connected device and return the result.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.executeAsync">executeAsync</a></td>
+<td>Public method to execute a series of commands over a period of time without returning any result (asynchronous execution).</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.handlePreferencesChanged">handlePreferencesChanged</a></td>
+<td>Public slot to handle a change of the preferences.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.isConnected">isConnected</a></td>
+<td>Public method to get the connection status.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.probeDevice">probeDevice</a></td>
+<td>Public method to check the device is responding.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonSerialDeviceInterface.write">write</a></td>
+<td>Public method to write data to the connected device.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="MicroPythonSerialDeviceInterface.__init__" ID="MicroPythonSerialDeviceInterface.__init__"></a>
+<h4>MicroPythonSerialDeviceInterface (Constructor)</h4>
+<b>MicroPythonSerialDeviceInterface</b>(<i>parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>parent</i> (QObject)</dt>
+<dd>
+reference to the parent object
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.__executeAsyncPaste" ID="MicroPythonSerialDeviceInterface.__executeAsyncPaste"></a>
+<h4>MicroPythonSerialDeviceInterface.__executeAsyncPaste</h4>
+<b>__executeAsyncPaste</b>(<i>commandsList</i>)
+
+<p>
+        Private method to execute a series of commands over a period of time
+        without returning any result (asynchronous execution).
+</p>
+<dl>
+
+<dt><i>commandsList</i> (list of str)</dt>
+<dd>
+list of commands to be execute on the device
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.__executeAsyncRaw" ID="MicroPythonSerialDeviceInterface.__executeAsyncRaw"></a>
+<h4>MicroPythonSerialDeviceInterface.__executeAsyncRaw</h4>
+<b>__executeAsyncRaw</b>(<i>commandsList</i>)
+
+<p>
+        Private method to execute a series of commands over a period of time
+        without returning any result (asynchronous execution).
+</p>
+<dl>
+
+<dt><i>commandsList</i> (list of bytes)</dt>
+<dd>
+list of commands to be execute on the device
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.__execute_paste" ID="MicroPythonSerialDeviceInterface.__execute_paste"></a>
+<h4>MicroPythonSerialDeviceInterface.__execute_paste</h4>
+<b>__execute_paste</b>(<i>commands, timeout=0</i>)
+
+<p>
+        Private method to send commands to the connected device using 'paste' mode
+        and return the result.
+</p>
+<p>
+        If no serial connection is available, empty results will be returned.
+</p>
+<dl>
+
+<dt><i>commands</i> (str or list of str)</dt>
+<dd>
+list of commands to be executed
+</dd>
+<dt><i>timeout</i> (int (optional))</dt>
+<dd>
+per command timeout in milliseconds (0 for configured default)
+            (defaults to 0)
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing stdout and stderr output of the device
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bytes, bytes)
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.__execute_raw" ID="MicroPythonSerialDeviceInterface.__execute_raw"></a>
+<h4>MicroPythonSerialDeviceInterface.__execute_raw</h4>
+<b>__execute_raw</b>(<i>commands, timeout=0</i>)
+
+<p>
+        Private method to send commands to the connected device using 'raw REPL' mode
+        and return the result.
+</p>
+<p>
+        If no serial connection is available, empty results will be returned.
+</p>
+<dl>
+
+<dt><i>commands</i> (str or list of str)</dt>
+<dd>
+list of commands to be executed
+</dd>
+<dt><i>timeout</i> (int (optional))</dt>
+<dd>
+per command timeout in milliseconds (0 for configured default)
+            (defaults to 0)
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing stdout and stderr output of the device
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bytes, bytes)
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.__pasteOff" ID="MicroPythonSerialDeviceInterface.__pasteOff"></a>
+<h4>MicroPythonSerialDeviceInterface.__pasteOff</h4>
+<b>__pasteOff</b>(<i></i>)
+
+<p>
+        Private method to switch 'paste' mode off.
+</p>
+<a NAME="MicroPythonSerialDeviceInterface.__pasteOn" ID="MicroPythonSerialDeviceInterface.__pasteOn"></a>
+<h4>MicroPythonSerialDeviceInterface.__pasteOn</h4>
+<b>__pasteOn</b>(<i></i>)
+
+<p>
+        Private method to switch the connected device to 'paste' mode.
+</p>
+<p>
+        Note: switching to paste mode is done with synchronous writes.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.__rawOff" ID="MicroPythonSerialDeviceInterface.__rawOff"></a>
+<h4>MicroPythonSerialDeviceInterface.__rawOff</h4>
+<b>__rawOff</b>(<i></i>)
+
+<p>
+        Private method to switch 'raw' mode off.
+</p>
+<a NAME="MicroPythonSerialDeviceInterface.__rawOn" ID="MicroPythonSerialDeviceInterface.__rawOn"></a>
+<h4>MicroPythonSerialDeviceInterface.__rawOn</h4>
+<b>__rawOn</b>(<i></i>)
+
+<p>
+        Private method to switch the connected device to 'raw' mode.
+</p>
+<p>
+        Note: switching to raw mode is done with synchronous writes.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.__readSerial" ID="MicroPythonSerialDeviceInterface.__readSerial"></a>
+<h4>MicroPythonSerialDeviceInterface.__readSerial</h4>
+<b>__readSerial</b>(<i></i>)
+
+<p>
+        Private slot to read all available serial data and emit it with the
+        "dataReceived" signal for further processing.
+</p>
+<a NAME="MicroPythonSerialDeviceInterface.connectToDevice" ID="MicroPythonSerialDeviceInterface.connectToDevice"></a>
+<h4>MicroPythonSerialDeviceInterface.connectToDevice</h4>
+<b>connectToDevice</b>(<i>connection</i>)
+
+<p>
+        Public slot to connect to the device.
+</p>
+<dl>
+
+<dt><i>connection</i> (str)</dt>
+<dd>
+name of the connection to be used
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.disconnectFromDevice" ID="MicroPythonSerialDeviceInterface.disconnectFromDevice"></a>
+<h4>MicroPythonSerialDeviceInterface.disconnectFromDevice</h4>
+<b>disconnectFromDevice</b>(<i></i>)
+
+<p>
+        Public slot to disconnect from the device.
+</p>
+<a NAME="MicroPythonSerialDeviceInterface.execute" ID="MicroPythonSerialDeviceInterface.execute"></a>
+<h4>MicroPythonSerialDeviceInterface.execute</h4>
+<b>execute</b>(<i>commands, *, mode="raw", timeout=0</i>)
+
+<p>
+        Public method to send commands to the connected device and return the
+        result.
+</p>
+<p>
+        If no serial connection is available, empty results will be returned.
+</p>
+<dl>
+
+<dt><i>commands</i> (str or list of str)</dt>
+<dd>
+list of commands to be executed
+</dd>
+<dt><i>mode=</i> (str)</dt>
+<dd>
+submit mode to be used (one of 'raw' or 'paste') (defaults to
+            'raw')
+</dd>
+<dt><i>timeout=</i> (int (optional))</dt>
+<dd>
+per command timeout in milliseconds (0 for configured default)
+            (defaults to 0)
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing stdout and stderr output of the device
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bytes, bytes)
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>ValueError</b>:</dt>
+<dd>
+raised in case of an unsupported submit mode
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.executeAsync" ID="MicroPythonSerialDeviceInterface.executeAsync"></a>
+<h4>MicroPythonSerialDeviceInterface.executeAsync</h4>
+<b>executeAsync</b>(<i>commandsList, submitMode</i>)
+
+<p>
+        Public method to execute a series of commands over a period of time
+        without returning any result (asynchronous execution).
+</p>
+<dl>
+
+<dt><i>commandsList</i> (list of str)</dt>
+<dd>
+list of commands to be execute on the device
+</dd>
+<dt><i>submitMode</i> (str (one of 'raw' or 'paste'))</dt>
+<dd>
+mode to be used to submit the commands
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>ValueError</b>:</dt>
+<dd>
+raised to indicate an unknown submit mode
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.handlePreferencesChanged" ID="MicroPythonSerialDeviceInterface.handlePreferencesChanged"></a>
+<h4>MicroPythonSerialDeviceInterface.handlePreferencesChanged</h4>
+<b>handlePreferencesChanged</b>(<i></i>)
+
+<p>
+        Public slot to handle a change of the preferences.
+</p>
+<a NAME="MicroPythonSerialDeviceInterface.isConnected" ID="MicroPythonSerialDeviceInterface.isConnected"></a>
+<h4>MicroPythonSerialDeviceInterface.isConnected</h4>
+<b>isConnected</b>(<i></i>)
+
+<p>
+        Public method to get the connection status.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating the connection status
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.probeDevice" ID="MicroPythonSerialDeviceInterface.probeDevice"></a>
+<h4>MicroPythonSerialDeviceInterface.probeDevice</h4>
+<b>probeDevice</b>(<i></i>)
+
+<p>
+        Public method to check the device is responding.
+</p>
+<p>
+        If the device has not been flashed with a MicroPython firmware, the
+        probe will fail.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating a communicating MicroPython device
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="MicroPythonSerialDeviceInterface.write" ID="MicroPythonSerialDeviceInterface.write"></a>
+<h4>MicroPythonSerialDeviceInterface.write</h4>
+<b>write</b>(<i>data</i>)
+
+<p>
+        Public method to write data to the connected device.
+</p>
+<dl>
+
+<dt><i>data</i> (bytes or bytearray)</dt>
+<dd>
+data to be written
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonWidget.html	Thu Apr 27 17:59:09 2023 +0200
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonWidget.html	Fri Apr 28 12:07:41 2023 +0200
@@ -52,7 +52,7 @@
 <h3>Class Attributes</h3>
 
 <table>
-<tr><td>DeviceBoardRole</td></tr><tr><td>DevicePidRole</td></tr><tr><td>DevicePortRole</td></tr><tr><td>DeviceSerNoRole</td></tr><tr><td>DeviceTypeRole</td></tr><tr><td>DeviceVidRole</td></tr><tr><td>ManualMarker</td></tr><tr><td>ZoomMax</td></tr><tr><td>ZoomMin</td></tr>
+<tr><td>DeviceBoardRole</td></tr><tr><td>DeviceInterfaceTypeRole</td></tr><tr><td>DevicePidRole</td></tr><tr><td>DevicePortRole</td></tr><tr><td>DeviceSerNoRole</td></tr><tr><td>DeviceTypeRole</td></tr><tr><td>DeviceVidRole</td></tr><tr><td>ManualMarker</td></tr><tr><td>ZoomMax</td></tr><tr><td>ZoomMin</td></tr>
 </table>
 <h3>Class Methods</h3>
 
@@ -228,10 +228,6 @@
 <td>Public method to process events for the REPL pane.</td>
 </tr>
 <tr>
-<td><a href="#MicroPythonWidget.getCurrentBoard">getCurrentBoard</a></td>
-<td>Public method to get the board name of the selected device.</td>
-</tr>
-<tr>
 <td><a href="#MicroPythonWidget.getCurrentPort">getCurrentPort</a></td>
 <td>Public method to determine the port path of the selected device.</td>
 </tr>
@@ -388,6 +384,13 @@
             automatically
 </dd>
 </dl>
+<dl>
+
+<dt>Raises <b>ValueError</b>:</dt>
+<dd>
+raised to indicate an unsupported interface type
+</dd>
+</dl>
 <a NAME="MicroPythonWidget.__convertToUF2" ID="MicroPythonWidget.__convertToUF2"></a>
 <h4>MicroPythonWidget.__convertToUF2</h4>
 <b>__convertToUF2</b>(<i></i>)
@@ -847,25 +850,6 @@
 bool
 </dd>
 </dl>
-<a NAME="MicroPythonWidget.getCurrentBoard" ID="MicroPythonWidget.getCurrentBoard"></a>
-<h4>MicroPythonWidget.getCurrentBoard</h4>
-<b>getCurrentBoard</b>(<i></i>)
-
-<p>
-        Public method to get the board name of the selected device.
-</p>
-<dl>
-<dt>Return:</dt>
-<dd>
-board name of the selected device
-</dd>
-</dl>
-<dl>
-<dt>Return Type:</dt>
-<dd>
-str
-</dd>
-</dl>
 <a NAME="MicroPythonWidget.getCurrentPort" ID="MicroPythonWidget.getCurrentPort"></a>
 <h4>MicroPythonWidget.getCurrentPort</h4>
 <b>getCurrentPort</b>(<i></i>)
--- a/src/eric7/Documentation/Source/index-eric7.MicroPython.html	Thu Apr 27 17:59:09 2023 +0200
+++ b/src/eric7/Documentation/Source/index-eric7.MicroPython.html	Fri Apr 28 12:07:41 2023 +0200
@@ -61,7 +61,7 @@
 </tr>
 <tr>
 <td><a href="eric7.MicroPython.MicroPythonDeviceInterface.html">MicroPythonDeviceInterface</a></td>
-<td>Module implementing some file system commands for MicroPython.</td>
+<td>Module  implementing an interface base class to talk to a connected MicroPython device.</td>
 </tr>
 <tr>
 <td><a href="eric7.MicroPython.MicroPythonFileManager.html">MicroPythonFileManager</a></td>
@@ -84,6 +84,10 @@
 <td>Module implementing a dialog to show progress messages.</td>
 </tr>
 <tr>
+<td><a href="eric7.MicroPython.MicroPythonSerialDeviceInterface.html">MicroPythonSerialDeviceInterface</a></td>
+<td>Module  implementing an interface to talk to a connected MicroPython device via a serial link.</td>
+</tr>
+<tr>
 <td><a href="eric7.MicroPython.MicroPythonSerialPort.html">MicroPythonSerialPort</a></td>
 <td>Module implementing a QSerialPort with additional functionality for MicroPython devices.</td>
 </tr>
--- a/src/eric7/MicroPython/MicroPythonDeviceInterface.py	Thu Apr 27 17:59:09 2023 +0200
+++ b/src/eric7/MicroPython/MicroPythonDeviceInterface.py	Fri Apr 28 12:07:41 2023 +0200
@@ -1,25 +1,13 @@
 # -*- coding: utf-8 -*-
 
-# Copyright (c) 2019 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
 #
 
 """
-Module implementing some file system commands for MicroPython.
+Module  implementing an interface base class to talk to a connected MicroPython device.
 """
 
-from PyQt6.QtCore import (
-    QCoreApplication,
-    QEventLoop,
-    QObject,
-    QThread,
-    QTimer,
-    pyqtSignal,
-    pyqtSlot,
-)
-
-from eric7 import Preferences
-
-from .MicroPythonSerialPort import MicroPythonSerialPort
+from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot
 
 
 class MicroPythonDeviceInterface(QObject):
@@ -28,16 +16,13 @@
 
     @signal executeAsyncFinished() emitted to indicate the end of an
         asynchronously executed list of commands (e.g. a script)
-    @signal dataReceived(data) emitted to send data received via the serial
-        connection for further processing
+    @signal dataReceived(data) emitted to send data received via the connection
+        for further processing
     """
 
     executeAsyncFinished = pyqtSignal()
     dataReceived = pyqtSignal(bytes)
 
-    PasteModePrompt = b"=== "
-    TracebackMarker = b"Traceback (most recent call last):"
-
     def __init__(self, parent=None):
         """
         Constructor
@@ -47,43 +32,35 @@
         """
         super().__init__(parent)
 
-        self.__repl = parent
-
-        self.__blockReadyRead = False
-
-        self.__serial = MicroPythonSerialPort(
-            timeout=Preferences.getMicroPython("SerialTimeout"), parent=self
-        )
-        self.__serial.readyRead.connect(self.__readSerial)
-
     @pyqtSlot()
-    def __readSerial(self):
+    def connectToDevice(self, connection):
         """
-        Private slot to read all available serial data and emit it with the
-        "dataReceived" signal for further processing.
-        """
-        if not self.__blockReadyRead:
-            data = bytes(self.__serial.readAll())
-            self.dataReceived.emit(data)
+        Public slot to connect to the device.
 
-    @pyqtSlot()
-    def connectToDevice(self, port):
-        """
-        Public slot to start the manager.
-
-        @param port name of the port to be used
+        @param connection name of the connection to be used
         @type str
         @return flag indicating success
         @rtype bool
+        @exception NotImplementedError raised to indicate that this method needs to
+            be implemented in a derived class
         """
-        return self.__serial.openSerialLink(port)
+        raise NotImplementedError(
+            "This method needs to be implemented in a derived class."
+        )
+
+        return False
 
     @pyqtSlot()
     def disconnectFromDevice(self):
         """
-        Public slot to stop the thread.
+        Public slot to disconnect from the device.
+
+        @exception NotImplementedError raised to indicate that this method needs to
+            be implemented in a derived class
         """
-        self.__serial.closeSerialLink()
+        raise NotImplementedError(
+            "This method needs to be implemented in a derived class."
+        )
 
     def isConnected(self):
         """
@@ -91,15 +68,21 @@
 
         @return flag indicating the connection status
         @rtype bool
+        @exception NotImplementedError raised to indicate that this method needs to
+            be implemented in a derived class
         """
-        return self.__serial.isConnected()
+        raise NotImplementedError(
+            "This method needs to be implemented in a derived class."
+        )
+
+        return False
 
     @pyqtSlot()
     def handlePreferencesChanged(self):
         """
         Public slot to handle a change of the preferences.
         """
-        self.__serial.setTimeout(Preferences.getMicroPython("SerialTimeout"))
+        pass
 
     def write(self, data):
         """
@@ -107,149 +90,37 @@
 
         @param data data to be written
         @type bytes or bytearray
-        """
-        self.__serial.isConnected() and self.__serial.write(data)
-
-    def __pasteOn(self):
-        """
-        Private method to switch the connected device to 'paste' mode.
-
-        Note: switching to paste mode is done with synchronous writes.
-
-        @return flag indicating success
-        @rtype bool
-        """
-        if not self.__serial:
-            return False
-
-        pasteMessage = b"paste mode; Ctrl-C to cancel, Ctrl-D to finish\r\n=== "
-
-        self.__serial.clear()  # clear any buffered output before entering paste mode
-        self.__serial.write(b"\x02")  # end raw mode if required
-        written = self.__serial.waitForBytesWritten(500)
-        # time out after 500ms if device is not responding
-        if not written:
-            return False
-        for _i in range(3):
-            # CTRL-C three times to break out of loops
-            self.__serial.write(b"\r\x03")
-            written = self.__serial.waitForBytesWritten(500)
-            # time out after 500ms if device is not responding
-            if not written:
-                return False
-            QThread.msleep(10)
-        self.__serial.readAll()  # read all data and discard it
-        self.__serial.write(b"\r\x05")  # send CTRL-E to enter paste mode
-        self.__serial.readUntil(pasteMessage)
-
-        if self.__serial.hasTimedOut():
-            # it timed out; try it again and than fail
-            self.__serial.write(b"\r\x05")  # send CTRL-E again
-            self.__serial.readUntil(pasteMessage)
-            if self.__serial.hasTimedOut():
-                return False
-
-        QCoreApplication.processEvents(
-            QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents
-        )
-        self.__serial.readAll()  # read all data and discard it
-        return True
-
-    def __pasteOff(self):
-        """
-        Private method to switch 'paste' mode off.
+        @exception NotImplementedError raised to indicate that this method needs to
+            be implemented in a derived class
         """
-        if self.__serial:
-            self.__serial.write(b"\x04")  # send CTRL-D to cancel paste mode
-
-    def __rawOn(self):
-        """
-        Private method to switch the connected device to 'raw' mode.
-
-        Note: switching to raw mode is done with synchronous writes.
-
-        @return flag indicating success
-        @rtype bool
-        """
-        if not self.__serial:
-            return False
-
-        rawReplMessage = b"raw REPL; CTRL-B to exit\r\n>"
-
-        self.__serial.write(b"\x02")  # end raw mode if required
-        written = self.__serial.waitForBytesWritten(500)
-        # time out after 500ms if device is not responding
-        if not written:
-            return False
-        for _i in range(3):
-            # CTRL-C three times to break out of loops
-            self.__serial.write(b"\r\x03")
-            written = self.__serial.waitForBytesWritten(500)
-            # time out after 500ms if device is not responding
-            if not written:
-                return False
-            QThread.msleep(10)
-        self.__serial.readAll()  # read all data and discard it
-        self.__serial.write(b"\r\x01")  # send CTRL-A to enter raw mode
-        self.__serial.readUntil(rawReplMessage)
-        if self.__serial.hasTimedOut():
-            # it timed out; try it again and than fail
-            self.__serial.write(b"\r\x01")  # send CTRL-A again
-            self.__serial.readUntil(rawReplMessage)
-            if self.__serial.hasTimedOut():
-                return False
-
-        QCoreApplication.processEvents(
-            QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents
+        raise NotImplementedError(
+            "This method needs to be implemented in a derived class."
         )
-        self.__serial.readAll()  # read all data and discard it
-        return True
-
-    def __rawOff(self):
-        """
-        Private method to switch 'raw' mode off.
-        """
-        if self.__serial:
-            self.__serial.write(b"\x02")  # send CTRL-B to cancel raw mode
-            self.__serial.readUntil(b">>> ")  # read until Python prompt
-            self.__serial.readAll()  # read all data and discard it
 
     def probeDevice(self):
         """
         Public method to check the device is responding.
 
-        If the device has not been flashed with a MicroPython formware, the
+        If the device has not been flashed with a MicroPython firmware, the
         probe will fail.
 
         @return flag indicating a communicating MicroPython device
         @rtype bool
+        @exception NotImplementedError raised to indicate that this method needs to
+            be implemented in a derived class
         """
-        if not self.__serial:
-            return False
-
-        if not self.__serial.isConnected():
-            return False
+        raise NotImplementedError(
+            "This method needs to be implemented in a derived class."
+        )
 
-        # switch on raw mode
-        self.__blockReadyRead = True
-        ok = self.__pasteOn()
-        if not ok:
-            self.__blockReadyRead = False
-            return False
-
-        # switch off raw mode
-        QThread.msleep(10)
-        self.__pasteOff()
-        self.__blockReadyRead = False
-
-        return True
+        return False
 
     def execute(self, commands, *, mode="raw", timeout=0):
         """
         Public method to send commands to the connected device and return the
         result.
 
-        If no serial connection is available, empty results will be returned.
+        If no connection is available, empty results will be returned.
 
         @param commands list of commands to be executed
         @type str or list of str
@@ -261,171 +132,18 @@
         @type int (optional)
         @return tuple containing stdout and stderr output of the device
         @rtype tuple of (bytes, bytes)
+        @exception NotImplementedError raised to indicate that this method needs to
+            be implemented in a derived class
         @exception ValueError raised in case of an unsupported submit mode
         """
+        raise NotImplementedError(
+            "This method needs to be implemented in a derived class."
+        )
+
         if mode not in ("paste", "raw"):
             raise ValueError("Unsupported submit mode given ('{0}').".format(mode))
 
-        if mode == "raw":
-            return self.__execute_raw(commands, timeout=timeout)
-        elif mode == "paste":
-            return self.__execute_paste(commands, timeout=timeout)
-        else:
-            # just in case
-            return b"", b""
-
-    def __execute_raw(self, commands, timeout=0):
-        """
-        Private method to send commands to the connected device using 'raw REPL' mode
-        and return the result.
-
-        If no serial connection is available, empty results will be returned.
-
-        @param commands list of commands to be executed
-        @type str or list of str
-        @param timeout per command timeout in milliseconds (0 for configured default)
-            (defaults to 0)
-        @type int (optional)
-        @return tuple containing stdout and stderr output of the device
-        @rtype tuple of (bytes, bytes)
-        """
-        if not self.__serial:
-            return b"", b""
-
-        if not self.__serial.isConnected():
-            return b"", b"Device not connected or not switched on."
-
-        result = bytearray()
-        err = b""
-
-        if isinstance(commands, str):
-            commands = [commands]
-
-        # switch on raw mode
-        self.__blockReadyRead = True
-        ok = self.__rawOn()
-        if not ok:
-            self.__blockReadyRead = False
-            return (b"", b"Could not switch to raw mode. Is the device switched on?")
-
-        # send commands
-        QThread.msleep(10)
-        for command in commands:
-            if command:
-                commandBytes = command.encode("utf-8")
-                self.__serial.write(commandBytes + b"\x04")
-                QCoreApplication.processEvents(
-                    QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents
-                )
-                ok = self.__serial.readUntil(b"OK")
-                if ok != b"OK":
-                    self.__blockReadyRead = False
-                    return (
-                        b"",
-                        "Expected 'OK', got '{0}', followed by '{1}'".format(
-                            ok, self.__serial.readAll()
-                        ).encode("utf-8"),
-                    )
-
-                # read until prompt
-                response = self.__serial.readUntil(b"\x04>", timeout=timeout)
-                if self.__serial.hasTimedOut():
-                    self.__blockReadyRead = False
-                    return b"", b"Timeout while processing commands."
-                if b"\x04" in response[:-2]:
-                    # split stdout, stderr
-                    out, err = response[:-2].split(b"\x04")
-                    result += out
-                else:
-                    err = b"invalid response received: " + response
-                if err:
-                    result = b""
-                    break
-
-        # switch off raw mode
-        QThread.msleep(10)
-        self.__rawOff()
-        self.__blockReadyRead = False
-
-        return bytes(result), err
-
-    def __execute_paste(self, commands, timeout=0):
-        """
-        Private method to send commands to the connected device using 'paste' mode
-        and return the result.
-
-        If no serial connection is available, empty results will be returned.
-
-        @param commands list of commands to be executed
-        @type str or list of str
-        @param timeout per command timeout in milliseconds (0 for configured default)
-            (defaults to 0)
-        @type int (optional)
-        @return tuple containing stdout and stderr output of the device
-        @rtype tuple of (bytes, bytes)
-        """
-        if not self.__serial:
-            return b"", b""
-
-        if not self.__serial.isConnected():
-            return b"", b"Device not connected or not switched on."
-
-        if isinstance(commands, list):
-            commands = "\n".join(commands)
-
-        # switch on paste mode
-        self.__blockReadyRead = True
-        ok = self.__pasteOn()
-        if not ok:
-            self.__blockReadyRead = False
-            return (b"", b"Could not switch to paste mode. Is the device switched on?")
-
-        # send commands
-        QThread.msleep(10)
-        for command in commands.splitlines(keepends=True):
-            # send the data as single lines
-            commandBytes = command.encode("utf-8")
-            self.__serial.write(commandBytes)
-            QCoreApplication.processEvents(
-                QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents
-            )
-            QThread.msleep(10)
-            ok = self.__serial.readUntil(commandBytes)
-            if ok != commandBytes:
-                self.__blockReadyRead = False
-                return (
-                    b"",
-                    "Expected '{0}', got '{1}', followed by '{2}'".format(
-                        commandBytes, ok, self.__serial.readAll()
-                    ).encode("utf-8"),
-                )
-
-        # switch off paste mode causing the commands to be executed
-        self.__pasteOff()
-        QThread.msleep(10)
-        # read until Python prompt
-        result = (
-            self.__serial.readUntil(b">>> ", timeout=timeout)
-            .replace(b">>> ", b"")
-            .strip()
-        )
-        if self.__serial.hasTimedOut():
-            self.__blockReadyRead = False
-            return b"", b"Timeout while processing commands."
-
-        # get rid of any OSD string
-        if result.startswith(b"\x1b]0;"):
-            result = result.split(b"\x1b\\")[-1]
-
-        if self.TracebackMarker in result:
-            errorIndex = result.find(self.TracebackMarker)
-            out, err = result[:errorIndex], result[errorIndex:]
-        else:
-            out = result
-            err = b""
-
-        self.__blockReadyRead = False
-        return out, err
+        return b"", b""
 
     def executeAsync(self, commandsList, submitMode):
         """
@@ -434,61 +152,18 @@
 
         @param commandsList list of commands to be execute on the device
         @type list of str
-        @param submitMode mode to be used to submit the commands
-        @type str (one of 'raw' or 'paste')
+        @param submitMode mode to be used to submit the commands (one of 'raw'
+            or 'paste')
+        @type str
+        @exception NotImplementedError raised to indicate that this method needs to
+            be implemented in a derived class
         @exception ValueError raised to indicate an unknown submit mode
         """
-        if submitMode not in ("raw", "paste"):
-            raise ValueError("Illegal submit mode given ({0})".format(submitMode))
-
-        if submitMode == "raw":
-            startSequence = [  # 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
-                b'print("\\n")\r',
-            ]
-            endSequence = [
-                b"\r",
-                b"\x04",
-            ]
-            self.__executeAsyncRaw(
-                startSequence
-                + [c.encode("utf-8") + b"\r" for c in commandsList]
-                + endSequence
-            )
-        elif submitMode == "paste":
-            self.__executeAsyncPaste(commandsList)
-
-    def __executeAsyncRaw(self, commandsList):
-        """
-        Private method to execute a series of commands over a period of time
-        without returning any result (asynchronous execution).
+        raise NotImplementedError(
+            "This method needs to be implemented in a derived class."
+        )
 
-        @param commandsList list of commands to be execute on the device
-        @type list of bytes
-        """
-        if commandsList:
-            command = commandsList.pop(0)
-            self.__serial.write(command)
-            QTimer.singleShot(2, lambda: self.__executeAsyncRaw(commandsList))
-        else:
-            self.__rawOff()
-            self.executeAsyncFinished.emit()
-
-    def __executeAsyncPaste(self, commandsList):
-        """
-        Private method to execute a series of commands over a period of time
-        without returning any result (asynchronous execution).
-
-        @param commandsList list of commands to be execute on the device
-        @type list of str
-        """
-        self.__blockReadyRead = True
-        self.__pasteOn()
-        command = b"\n".join(c.encode("utf-8)") for c in commandsList)
-        self.__serial.write(command)
-        self.__serial.readUntil(command)
-        self.__blockReadyRead = False
-        self.__pasteOff()
-        self.executeAsyncFinished.emit
+        if submitMode not in ("raw", "paste"):
+            raise ValueError(
+                "Unsupported submit mode given ('{0}').".format(submitMode)
+            )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/MicroPythonSerialDeviceInterface.py	Fri Apr 28 12:07:41 2023 +0200
@@ -0,0 +1,479 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module  implementing an interface to talk to a connected MicroPython device via
+a serial link.
+"""
+
+from PyQt6.QtCore import QCoreApplication, QEventLoop, QThread, QTimer, pyqtSlot
+
+from eric7 import Preferences
+
+from .MicroPythonDeviceInterface import MicroPythonDeviceInterface
+from .MicroPythonSerialPort import MicroPythonSerialPort
+
+
+class MicroPythonSerialDeviceInterface(MicroPythonDeviceInterface):
+    """
+    Class implementing an interface to talk to a connected MicroPython device via
+    a serial link.
+    """
+
+    PasteModePrompt = b"=== "
+    TracebackMarker = b"Traceback (most recent call last):"
+
+    def __init__(self, parent=None):
+        """
+        Constructor
+
+        @param parent reference to the parent object
+        @type QObject
+        """
+        super().__init__(parent)
+
+        self.__blockReadyRead = False
+
+        self.__serial = MicroPythonSerialPort(
+            timeout=Preferences.getMicroPython("SerialTimeout"), parent=self
+        )
+        self.__serial.readyRead.connect(self.__readSerial)
+
+    @pyqtSlot()
+    def __readSerial(self):
+        """
+        Private slot to read all available serial data and emit it with the
+        "dataReceived" signal for further processing.
+        """
+        if not self.__blockReadyRead:
+            data = bytes(self.__serial.readAll())
+            self.dataReceived.emit(data)
+
+    @pyqtSlot()
+    def connectToDevice(self, connection):
+        """
+        Public slot to connect to the device.
+
+        @param connection name of the connection to be used
+        @type str
+        @return flag indicating success
+        @rtype bool
+        """
+        return self.__serial.openSerialLink(connection)
+
+    @pyqtSlot()
+    def disconnectFromDevice(self):
+        """
+        Public slot to disconnect from the device.
+        """
+        self.__serial.closeSerialLink()
+
+    def isConnected(self):
+        """
+        Public method to get the connection status.
+
+        @return flag indicating the connection status
+        @rtype bool
+        """
+        return self.__serial.isConnected()
+
+    @pyqtSlot()
+    def handlePreferencesChanged(self):
+        """
+        Public slot to handle a change of the preferences.
+        """
+        self.__serial.setTimeout(Preferences.getMicroPython("SerialTimeout"))
+
+    def write(self, data):
+        """
+        Public method to write data to the connected device.
+
+        @param data data to be written
+        @type bytes or bytearray
+        """
+        self.__serial.isConnected() and self.__serial.write(data)
+
+    def __pasteOn(self):
+        """
+        Private method to switch the connected device to 'paste' mode.
+
+        Note: switching to paste mode is done with synchronous writes.
+
+        @return flag indicating success
+        @rtype bool
+        """
+        if not self.__serial:
+            return False
+
+        pasteMessage = b"paste mode; Ctrl-C to cancel, Ctrl-D to finish\r\n=== "
+
+        self.__serial.clear()  # clear any buffered output before entering paste mode
+        self.__serial.write(b"\x02")  # end raw mode if required
+        written = self.__serial.waitForBytesWritten(500)
+        # time out after 500ms if device is not responding
+        if not written:
+            return False
+        for _i in range(3):
+            # CTRL-C three times to break out of loops
+            self.__serial.write(b"\r\x03")
+            written = self.__serial.waitForBytesWritten(500)
+            # time out after 500ms if device is not responding
+            if not written:
+                return False
+            QThread.msleep(10)
+        self.__serial.readAll()  # read all data and discard it
+        self.__serial.write(b"\r\x05")  # send CTRL-E to enter paste mode
+        self.__serial.readUntil(pasteMessage)
+
+        if self.__serial.hasTimedOut():
+            # it timed out; try it again and than fail
+            self.__serial.write(b"\r\x05")  # send CTRL-E again
+            self.__serial.readUntil(pasteMessage)
+            if self.__serial.hasTimedOut():
+                return False
+
+        QCoreApplication.processEvents(
+            QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents
+        )
+        self.__serial.readAll()  # read all data and discard it
+        return True
+
+    def __pasteOff(self):
+        """
+        Private method to switch 'paste' mode off.
+        """
+        if self.__serial:
+            self.__serial.write(b"\x04")  # send CTRL-D to cancel paste mode
+
+    def __rawOn(self):
+        """
+        Private method to switch the connected device to 'raw' mode.
+
+        Note: switching to raw mode is done with synchronous writes.
+
+        @return flag indicating success
+        @rtype bool
+        """
+        if not self.__serial:
+            return False
+
+        rawReplMessage = b"raw REPL; CTRL-B to exit\r\n>"
+
+        self.__serial.write(b"\x02")  # end raw mode if required
+        written = self.__serial.waitForBytesWritten(500)
+        # time out after 500ms if device is not responding
+        if not written:
+            return False
+        for _i in range(3):
+            # CTRL-C three times to break out of loops
+            self.__serial.write(b"\r\x03")
+            written = self.__serial.waitForBytesWritten(500)
+            # time out after 500ms if device is not responding
+            if not written:
+                return False
+            QThread.msleep(10)
+        self.__serial.readAll()  # read all data and discard it
+        self.__serial.write(b"\r\x01")  # send CTRL-A to enter raw mode
+        self.__serial.readUntil(rawReplMessage)
+        if self.__serial.hasTimedOut():
+            # it timed out; try it again and than fail
+            self.__serial.write(b"\r\x01")  # send CTRL-A again
+            self.__serial.readUntil(rawReplMessage)
+            if self.__serial.hasTimedOut():
+                return False
+
+        QCoreApplication.processEvents(
+            QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents
+        )
+        self.__serial.readAll()  # read all data and discard it
+        return True
+
+    def __rawOff(self):
+        """
+        Private method to switch 'raw' mode off.
+        """
+        if self.__serial:
+            self.__serial.write(b"\x02")  # send CTRL-B to cancel raw mode
+            self.__serial.readUntil(b">>> ")  # read until Python prompt
+            self.__serial.readAll()  # read all data and discard it
+
+    def probeDevice(self):
+        """
+        Public method to check the device is responding.
+
+        If the device has not been flashed with a MicroPython firmware, the
+        probe will fail.
+
+        @return flag indicating a communicating MicroPython device
+        @rtype bool
+        """
+        if not self.__serial:
+            return False
+
+        if not self.__serial.isConnected():
+            return False
+
+        # switch on raw mode
+        self.__blockReadyRead = True
+        ok = self.__pasteOn()
+        if not ok:
+            self.__blockReadyRead = False
+            return False
+
+        # switch off raw mode
+        QThread.msleep(10)
+        self.__pasteOff()
+        self.__blockReadyRead = False
+
+        return True
+
+    def execute(self, commands, *, mode="raw", timeout=0):
+        """
+        Public method to send commands to the connected device and return the
+        result.
+
+        If no serial connection is available, empty results will be returned.
+
+        @param commands list of commands to be executed
+        @type str or list of str
+        @keyparam mode submit mode to be used (one of 'raw' or 'paste') (defaults to
+            'raw')
+        @type str
+        @keyparam timeout per command timeout in milliseconds (0 for configured default)
+            (defaults to 0)
+        @type int (optional)
+        @return tuple containing stdout and stderr output of the device
+        @rtype tuple of (bytes, bytes)
+        @exception ValueError raised in case of an unsupported submit mode
+        """
+        if mode not in ("paste", "raw"):
+            raise ValueError("Unsupported submit mode given ('{0}').".format(mode))
+
+        if mode == "raw":
+            return self.__execute_raw(commands, timeout=timeout)
+        elif mode == "paste":
+            return self.__execute_paste(commands, timeout=timeout)
+        else:
+            # just in case
+            return b"", b""
+
+    def __execute_raw(self, commands, timeout=0):
+        """
+        Private method to send commands to the connected device using 'raw REPL' mode
+        and return the result.
+
+        If no serial connection is available, empty results will be returned.
+
+        @param commands list of commands to be executed
+        @type str or list of str
+        @param timeout per command timeout in milliseconds (0 for configured default)
+            (defaults to 0)
+        @type int (optional)
+        @return tuple containing stdout and stderr output of the device
+        @rtype tuple of (bytes, bytes)
+        """
+        if not self.__serial:
+            return b"", b""
+
+        if not self.__serial.isConnected():
+            return b"", b"Device not connected or not switched on."
+
+        result = bytearray()
+        err = b""
+
+        if isinstance(commands, str):
+            commands = [commands]
+
+        # switch on raw mode
+        self.__blockReadyRead = True
+        ok = self.__rawOn()
+        if not ok:
+            self.__blockReadyRead = False
+            return (b"", b"Could not switch to raw mode. Is the device switched on?")
+
+        # send commands
+        QThread.msleep(10)
+        for command in commands:
+            if command:
+                commandBytes = command.encode("utf-8")
+                self.__serial.write(commandBytes + b"\x04")
+                QCoreApplication.processEvents(
+                    QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents
+                )
+                ok = self.__serial.readUntil(b"OK")
+                if ok != b"OK":
+                    self.__blockReadyRead = False
+                    return (
+                        b"",
+                        "Expected 'OK', got '{0}', followed by '{1}'".format(
+                            ok, self.__serial.readAll()
+                        ).encode("utf-8"),
+                    )
+
+                # read until prompt
+                response = self.__serial.readUntil(b"\x04>", timeout=timeout)
+                if self.__serial.hasTimedOut():
+                    self.__blockReadyRead = False
+                    return b"", b"Timeout while processing commands."
+                if b"\x04" in response[:-2]:
+                    # split stdout, stderr
+                    out, err = response[:-2].split(b"\x04")
+                    result += out
+                else:
+                    err = b"invalid response received: " + response
+                if err:
+                    result = b""
+                    break
+
+        # switch off raw mode
+        QThread.msleep(10)
+        self.__rawOff()
+        self.__blockReadyRead = False
+
+        return bytes(result), err
+
+    def __execute_paste(self, commands, timeout=0):
+        """
+        Private method to send commands to the connected device using 'paste' mode
+        and return the result.
+
+        If no serial connection is available, empty results will be returned.
+
+        @param commands list of commands to be executed
+        @type str or list of str
+        @param timeout per command timeout in milliseconds (0 for configured default)
+            (defaults to 0)
+        @type int (optional)
+        @return tuple containing stdout and stderr output of the device
+        @rtype tuple of (bytes, bytes)
+        """
+        if not self.__serial:
+            return b"", b""
+
+        if not self.__serial.isConnected():
+            return b"", b"Device not connected or not switched on."
+
+        if isinstance(commands, list):
+            commands = "\n".join(commands)
+
+        # switch on paste mode
+        self.__blockReadyRead = True
+        ok = self.__pasteOn()
+        if not ok:
+            self.__blockReadyRead = False
+            return (b"", b"Could not switch to paste mode. Is the device switched on?")
+
+        # send commands
+        QThread.msleep(10)
+        for command in commands.splitlines(keepends=True):
+            # send the data as single lines
+            commandBytes = command.encode("utf-8")
+            self.__serial.write(commandBytes)
+            QCoreApplication.processEvents(
+                QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents
+            )
+            QThread.msleep(10)
+            ok = self.__serial.readUntil(commandBytes)
+            if ok != commandBytes:
+                self.__blockReadyRead = False
+                return (
+                    b"",
+                    "Expected '{0}', got '{1}', followed by '{2}'".format(
+                        commandBytes, ok, self.__serial.readAll()
+                    ).encode("utf-8"),
+                )
+
+        # switch off paste mode causing the commands to be executed
+        self.__pasteOff()
+        QThread.msleep(10)
+        # read until Python prompt
+        result = (
+            self.__serial.readUntil(b">>> ", timeout=timeout)
+            .replace(b">>> ", b"")
+            .strip()
+        )
+        if self.__serial.hasTimedOut():
+            self.__blockReadyRead = False
+            return b"", b"Timeout while processing commands."
+
+        # get rid of any OSD string
+        if result.startswith(b"\x1b]0;"):
+            result = result.split(b"\x1b\\")[-1]
+
+        if self.TracebackMarker in result:
+            errorIndex = result.find(self.TracebackMarker)
+            out, err = result[:errorIndex], result[errorIndex:]
+        else:
+            out = result
+            err = b""
+
+        self.__blockReadyRead = False
+        return out, err
+
+    def executeAsync(self, commandsList, submitMode):
+        """
+        Public method to execute a series of commands over a period of time
+        without returning any result (asynchronous execution).
+
+        @param commandsList list of commands to be execute on the device
+        @type list of str
+        @param submitMode mode to be used to submit the commands
+        @type str (one of 'raw' or 'paste')
+        @exception ValueError raised to indicate an unknown submit mode
+        """
+        if submitMode not in ("raw", "paste"):
+            raise ValueError("Illegal submit mode given ({0})".format(submitMode))
+
+        if submitMode == "raw":
+            startSequence = [  # 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
+                b'print("\\n")\r',
+            ]
+            endSequence = [
+                b"\r",
+                b"\x04",
+            ]
+            self.__executeAsyncRaw(
+                startSequence
+                + [c.encode("utf-8") + b"\r" for c in commandsList]
+                + endSequence
+            )
+        elif submitMode == "paste":
+            self.__executeAsyncPaste(commandsList)
+
+    def __executeAsyncRaw(self, commandsList):
+        """
+        Private method to execute a series of commands over a period of time
+        without returning any result (asynchronous execution).
+
+        @param commandsList list of commands to be execute on the device
+        @type list of bytes
+        """
+        if commandsList:
+            command = commandsList.pop(0)
+            self.__serial.write(command)
+            QTimer.singleShot(2, lambda: self.__executeAsyncRaw(commandsList))
+        else:
+            self.__rawOff()
+            self.executeAsyncFinished.emit()
+
+    def __executeAsyncPaste(self, commandsList):
+        """
+        Private method to execute a series of commands over a period of time
+        without returning any result (asynchronous execution).
+
+        @param commandsList list of commands to be execute on the device
+        @type list of str
+        """
+        self.__blockReadyRead = True
+        self.__pasteOn()
+        command = b"\n".join(c.encode("utf-8)") for c in commandsList)
+        self.__serial.write(command)
+        self.__serial.readUntil(command)
+        self.__blockReadyRead = False
+        self.__pasteOff()
+        self.executeAsyncFinished.emit
--- a/src/eric7/MicroPython/MicroPythonWidget.py	Thu Apr 27 17:59:09 2023 +0200
+++ b/src/eric7/MicroPython/MicroPythonWidget.py	Fri Apr 28 12:07:41 2023 +0200
@@ -7,6 +7,10 @@
 Module implementing the MicroPython REPL widget.
 """
 
+# TODO: refactor the code such to have the MicroPythonWidget as the top level
+#       container and a MicroPythonReplWidget containing the REPL related stuff
+#       (incl. device status line and zoom widget ?)
+
 import contextlib
 import functools
 import os
@@ -57,7 +61,7 @@
     HAS_QTCHART = False
 
 try:
-    from .MicroPythonDeviceInterface import MicroPythonDeviceInterface
+    from .MicroPythonSerialDeviceInterface import MicroPythonSerialDeviceInterface
 
     HAS_QTSERIALPORT = True
 except ImportError:
@@ -211,6 +215,7 @@
     DeviceVidRole = Qt.ItemDataRole.UserRole + 3
     DevicePidRole = Qt.ItemDataRole.UserRole + 4
     DeviceSerNoRole = Qt.ItemDataRole.UserRole + 5
+    DeviceInterfaceTypeRole = Qt.ItemDataRole.UserRole + 6
 
     dataReceived = pyqtSignal(bytes)
 
@@ -290,10 +295,7 @@
         self.__lastPort = None
         self.__lastDeviceType = None
 
-        if HAS_QTSERIALPORT:
-            self.__interface = MicroPythonDeviceInterface(self)
-        else:
-            self.__interface = None
+        self.__interface = None
         self.__device = None
         self.__connected = False
         self.__linkConnected = False
@@ -324,7 +326,6 @@
 
         self.replEdit.customContextMenuRequested.connect(self.__showContextMenu)
         self.__ui.preferencesChanged.connect(self.__handlePreferencesChanged)
-        self.__ui.preferencesChanged.connect(self.__interface.handlePreferencesChanged)
 
         self.__handlePreferencesChanged()
 
@@ -376,6 +377,9 @@
                 self.deviceTypeComboBox.setItemData(
                     index, serialNumber, self.DeviceSerNoRole
                 )
+                self.deviceTypeComboBox.setItemData(
+                    index, "serial", self.DeviceInterfaceTypeRole
+                )
 
         else:
             supportedMessage = self.tr("No supported devices detected.")
@@ -478,6 +482,9 @@
         else:
             self.replEdit.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
 
+        if self.__interface is not None:
+            self.__interface.handlePreferencesChanged
+
         if self.__chartWidget is not None:
             self.__chartWidget.preferencesChanged()
 
@@ -622,7 +629,7 @@
         @type bool
         """
         self.__connected = connected
-        self.__linkConnected = self.__interface.isConnected()
+        self.__linkConnected = bool(self.__interface) and self.__interface.isConnected()
 
         self.deviceConnectedLed.setOn(self.__linkConnected)
         if self.__fileManagerWidget:
@@ -723,7 +730,8 @@
             self.replEdit.setFocus(Qt.FocusReason.OtherFocusReason)
         else:
             with contextlib.suppress(TypeError):
-                self.__interface.dataReceived.disconnect(self.__processData)
+                if self.__interface is not None:
+                    self.__interface.dataReceived.disconnect(self.__processData)
             if not self.chartButton.isChecked() and not self.filesButton.isChecked():
                 self.__disconnectFromDevice()
             self.__device.setRepl(False)
@@ -1134,16 +1142,6 @@
         else:
             return ""
 
-    def getCurrentBoard(self):
-        """
-        Public method to get the board name of the selected device.
-
-        @return board name of the selected device
-        @rtype str
-        """
-        boardName = self.deviceTypeComboBox.currentData(self.DeviceBoardRole)
-        return boardName
-
     def getDevice(self):
         """
         Public method to get a reference to the current device.
@@ -1182,27 +1180,44 @@
         @param withAutostart flag indicating to start the repl and file manager
             automatically
         @type bool
+        @exception ValueError raised to indicate an unsupported interface type
         """
         from .ConnectionSelectionDialog import ConnectionSelectionDialog
 
-        port = self.getCurrentPort()
-        if not port:
-            with EricOverridenCursor():
-                dlg = ConnectionSelectionDialog(
-                    self.__unknownPorts, self.__lastPort, self.__lastDeviceType
-                )
-                if dlg.exec() == QDialog.DialogCode.Accepted:
-                    vid, pid, port, deviceType = dlg.getData()
+        interfaceType = (
+            self.deviceTypeComboBox.currentData(self.DeviceInterfaceTypeRole)
+            or "serial"
+        )  # 'serial' is the default
+
+        if interfaceType not in ("serial", "webrepl"):
+            raise ValueError(
+                "Unsupported interface type detected ('{0}')".format(interfaceType)
+            )
 
-                    self.deviceIconLabel.setPixmap(
-                        Devices.getDeviceIcon(deviceType, False)
+        if interfaceType == "serial":
+            port = self.getCurrentPort()
+            if not port:
+                with EricOverridenCursor():
+                    dlg = ConnectionSelectionDialog(
+                        self.__unknownPorts, self.__lastPort, self.__lastDeviceType
                     )
-                    self.__device = Devices.getDevice(deviceType, self, vid, pid)
+                    if dlg.exec() == QDialog.DialogCode.Accepted:
+                        vid, pid, port, deviceType = dlg.getData()
 
-                    self.__lastPort = port
-                    self.__lastDeviceType = deviceType
-                else:
-                    return
+                        self.deviceIconLabel.setPixmap(
+                            Devices.getDeviceIcon(deviceType, False)
+                        )
+                        self.__device = Devices.getDevice(deviceType, self, vid, pid)
+
+                        self.__lastPort = port
+                        self.__lastDeviceType = deviceType
+                    else:
+                        return
+
+            self.__interface = MicroPythonSerialDeviceInterface(self)
+        elif interfaceType == "webrepl":
+            # TODO: not yet implemented
+            return
 
         if self.__interface.connectToDevice(port):
             deviceResponding = self.__interface.probeDevice()
@@ -1250,9 +1265,13 @@
         Private method to disconnect from the device.
         """
         self.__device and self.__device.setConnected(False)
-        self.__interface.disconnectFromDevice()
         self.__setConnected(False)
 
+        if self.__interface is not None:
+            self.__interface.disconnectFromDevice()
+            self.__interface.deleteLater()
+            self.__interface = None
+
     @pyqtSlot()
     def on_runButton_clicked(self):
         """

eric ide

mercurial