Merged with branch 'eric7' to prepare documentation and translations update. mpy_network

Fri, 03 Mar 2023 11:31:53 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 03 Mar 2023 11:31:53 +0100
branch
mpy_network
changeset 9839
fc60e382b67a
parent 9838
d6b87ef03c13 (diff)
parent 9831
46e371226a22 (current diff)
child 9840
d41ee69fa69b

Merged with branch 'eric7' to prepare documentation and translations update.

src/eric7/APIs/Python3/eric7.api 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.MicroPythonWidget.html file | annotate | diff | comparison | revisions
--- a/docs/changelog.md	Wed Mar 01 09:03:13 2023 +0100
+++ b/docs/changelog.md	Fri Mar 03 11:31:53 2023 +0100
@@ -1,5 +1,10 @@
 # Change Log
 
+### Version 23.4
+- bug fixes
+- MicroPython
+    - Added functionality to search for known boot volumes in the UF2 flash dialog.
+
 ### Version 23.3
 - bug fixes
 - MicroPython
--- a/eric7.epj	Wed Mar 01 09:03:13 2023 +0100
+++ b/eric7.epj	Fri Mar 03 11:31:53 2023 +0100
@@ -63,7 +63,7 @@
         "CopyrightMinFileSize": 0,
         "DocstringType": "eric_black",
         "EnabledCheckerCategories": "C, D, E, I, M, N, Y, W",
-        "ExcludeFiles": "*/ThirdParty/*, */coverage/*, */Ui_*.py, */Examples/*, */pycodestyle.py,*/pyflakes/checker.py,*/mccabe.py,*/eradicate.py,*/ast_unparse.py,*/piplicenses.py,*/pipdeptree.py",
+        "ExcludeFiles": "*/ThirdParty/*, */coverage/*, */Ui_*.py, */Examples/*, */pycodestyle.py,*/pyflakes/checker.py,*/mccabe.py,*/eradicate.py,*/ast_unparse.py,*/piplicenses.py,*/pipdeptree.py,*/MCUScripts/*",
         "ExcludeMessages": "C101,E203,E265,E266,E305,E402,M201,M301,M302,M303,M304,M305,M306,M307,M308,M311,M312,M313,M314,M315,M321,M701,M702,M811,M834,N802,N803,N807,N808,N821,W293,W503,Y401,Y402",
         "FixCodes": "",
         "FixIssues": false,
@@ -310,6 +310,7 @@
       "src/eric7/Debugger/StartRunDialog.ui",
       "src/eric7/Debugger/VariableDetailDialog.ui",
       "src/eric7/Debugger/VariablesFilterDialog.ui",
+      "src/eric7/EricNetwork/EricIPv4InputWidget.ui",
       "src/eric7/EricNetwork/EricSslCertificateSelectionDialog.ui",
       "src/eric7/EricNetwork/EricSslCertificatesDialog.ui",
       "src/eric7/EricNetwork/EricSslCertificatesInfoDialog.ui",
@@ -347,6 +348,12 @@
       "src/eric7/MicroPython/ShowModulesDialog.ui",
       "src/eric7/MicroPython/UF2FlashDialog.ui",
       "src/eric7/MicroPython/UnknownDevicesDialog.ui",
+      "src/eric7/MicroPython/WifiDialogs/WifiApConfigDialog.ui",
+      "src/eric7/MicroPython/WifiDialogs/WifiApStationsDialog.ui",
+      "src/eric7/MicroPython/WifiDialogs/WifiConnectionDialog.ui",
+      "src/eric7/MicroPython/WifiDialogs/WifiCountryDialog.ui",
+      "src/eric7/MicroPython/WifiDialogs/WifiNetworksWindow.ui",
+      "src/eric7/MicroPython/WifiDialogs/WifiStatusDialog.ui",
       "src/eric7/MultiProject/AddProjectDialog.ui",
       "src/eric7/MultiProject/PropertiesDialog.ui",
       "src/eric7/Network/IRC/IrcChannelEditDialog.ui",
@@ -976,7 +983,7 @@
     "OTHERTOOLSPARMS": {
       "Black": {
         "exclude": "/(\\.direnv|\\.eggs|\\.git|\\.hg|\\.mypy_cache|\\.nox|\\.tox|\\.venv|venv|\\.svn|\\.ipynb_checkpoints|_build|buck-out|build|dist|__pypackages__)/",
-        "extend-exclude": "/(\n\tExamples/\n\t| ThirdParty/\n\t| coverage/\n\t| Ui_.*\\.py\n\t| pycodestyle\\.py\n\t| pyflakes/checker\\.py\n\t| mccabe\\.py\n\t| eradicate\\.py\n\t| ast_unparse\\.py\n\t| piplicenses\\.py\n\t| pipdeptree\\.py\n)",
+        "extend-exclude": "/(\n\tExamples/\n\t| ThirdParty/\n\t| coverage/\n  | MCUScripts/\n\t| Ui_.*\\.py\n\t| pycodestyle\\.py\n\t| pyflakes/checker\\.py\n\t| mccabe\\.py\n\t| eradicate\\.py\n\t| ast_unparse\\.py\n\t| piplicenses\\.py\n\t| pipdeptree\\.py\n)",
         "force-exclude": "",
         "line-length": 88,
         "skip-magic-trailing-comma": false,
@@ -1003,6 +1010,7 @@
           "*/Examples/*",
           "*/ThirdParty/*",
           "*/coverage/*",
+          "*/MCUScripts/*",
           "*/Ui_*.py",
           "*/pycodestyle.py",
           "*/pyflakes/checker.py",
@@ -1148,6 +1156,7 @@
       "src/eric7/EricNetwork/EricFtp.py",
       "src/eric7/EricNetwork/EricGoogleMail.py",
       "src/eric7/EricNetwork/EricGoogleMailHelpers.py",
+      "src/eric7/EricNetwork/EricIPv4InputWidget.py",
       "src/eric7/EricNetwork/EricJsonClient.py",
       "src/eric7/EricNetwork/EricJsonServer.py",
       "src/eric7/EricNetwork/EricJsonStreamReader.py",
@@ -1295,6 +1304,12 @@
       "src/eric7/MicroPython/Devices/EspDialogs/EspFirmwareSelectionDialog.py",
       "src/eric7/MicroPython/Devices/EspDialogs/__init__.py",
       "src/eric7/MicroPython/Devices/GenericMicroPythonDevices.py",
+      "src/eric7/MicroPython/Devices/MCUScripts/__init__.py",
+      "src/eric7/MicroPython/Devices/MCUScripts/circuitPy7WiFiConnect.py",
+      "src/eric7/MicroPython/Devices/MCUScripts/esp32WiFiConnect.py",
+      "src/eric7/MicroPython/Devices/MCUScripts/mpyWiFiConnect.py",
+      "src/eric7/MicroPython/Devices/MCUScripts/picowWiFiConnect.py",
+      "src/eric7/MicroPython/Devices/MCUScripts/pimoroniWiFiConnect.py",
       "src/eric7/MicroPython/Devices/MicrobitDevices.py",
       "src/eric7/MicroPython/Devices/PyBoardDevices.py",
       "src/eric7/MicroPython/Devices/RP2040Devices.py",
@@ -1312,6 +1327,14 @@
       "src/eric7/MicroPython/ShowModulesDialog.py",
       "src/eric7/MicroPython/UF2FlashDialog.py",
       "src/eric7/MicroPython/UnknownDevicesDialog.py",
+      "src/eric7/MicroPython/WifiDialogs/WifiApConfigDialog.py",
+      "src/eric7/MicroPython/WifiDialogs/WifiApStationsDialog.py",
+      "src/eric7/MicroPython/WifiDialogs/WifiConnectionDialog.py",
+      "src/eric7/MicroPython/WifiDialogs/WifiController.py",
+      "src/eric7/MicroPython/WifiDialogs/WifiCountryDialog.py",
+      "src/eric7/MicroPython/WifiDialogs/WifiNetworksWindow.py",
+      "src/eric7/MicroPython/WifiDialogs/WifiStatusDialog.py",
+      "src/eric7/MicroPython/WifiDialogs/__init__.py",
       "src/eric7/MicroPython/__init__.py",
       "src/eric7/MultiProject/AddProjectDialog.py",
       "src/eric7/MultiProject/MultiProject.py",
--- a/src/eric7/APIs/Python3/eric7.api	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/APIs/Python3/eric7.api	Fri Mar 03 11:31:53 2023 +0100
@@ -1124,6 +1124,15 @@
 eric7.EricNetwork.EricGoogleMailHelpers.TOKEN_FILE?7
 eric7.EricNetwork.EricGoogleMailHelpers.installGoogleAPIPackages?4()
 eric7.EricNetwork.EricGoogleMailHelpers.isClientSecretFileAvailable?4()
+eric7.EricNetwork.EricIPv4InputWidget.EricIPv4InputWidget.address?4()
+eric7.EricNetwork.EricIPv4InputWidget.EricIPv4InputWidget.addressChanged?7
+eric7.EricNetwork.EricIPv4InputWidget.EricIPv4InputWidget.clear?4()
+eric7.EricNetwork.EricIPv4InputWidget.EricIPv4InputWidget.eventFilter?4(obj, evt)
+eric7.EricNetwork.EricIPv4InputWidget.EricIPv4InputWidget.hasAcceptableInput?4()
+eric7.EricNetwork.EricIPv4InputWidget.EricIPv4InputWidget.setAddress?4(address)
+eric7.EricNetwork.EricIPv4InputWidget.EricIPv4InputWidget.setText?4(address)
+eric7.EricNetwork.EricIPv4InputWidget.EricIPv4InputWidget.text?4()
+eric7.EricNetwork.EricIPv4InputWidget.EricIPv4InputWidget?1(parent=None)
 eric7.EricNetwork.EricJsonClient.EricJsonClient.handleCall?4(method, params)
 eric7.EricNetwork.EricJsonClient.EricJsonClient.poll?4(waitMethod="")
 eric7.EricNetwork.EricJsonClient.EricJsonClient.run?4()
@@ -2590,43 +2599,55 @@
 eric7.MicroPython.Devices.DeviceBase.BaseDevice._getSetTimeCode?5()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice._shortError?5(error)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.addDeviceMenuEntries?4(menu)
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.addDeviceWifiEntries?4(menu)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.canRunScript?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.canStartFileManager?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.canStartPlotter?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.canStartRepl?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.cd?4(dirname)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.checkDeviceData?4(quiet=True)
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.checkInternet?4()
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.connectWifi?4(ssid, password)
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.deactivateInterface?4(interface)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.deviceName?4()
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.disconnectWifi?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.downloadFirmware?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.fileSystemInfo?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.forceInterrupt?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.get?4(deviceFileName, hostFileName=None)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.getBoardInformation?4()
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.getConnectedClients?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.getData?4(deviceFileName)
-eric7.MicroPython.Devices.DeviceBase.BaseDevice.getDeviceData?4()
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.getDeviceData?4(key=None)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.getDeviceType?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.getDocumentationUrl?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.getDownloadMenuEntries?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.getFirmwareUrl?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.getModules?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.getTime?4()
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.getWifiData?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.getWorkspace?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.handleDataFlood?4()
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.hasBluetooth?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.hasCircuitPython?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.hasDocumentationUrl?4()
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.hasEthernet?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.hasFirmwareUrl?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.hasFlashMenuEntry?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.hasTimeCommands?4()
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.hasWifi?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.lls?4(dirname="", fullstat=False, showHidden=False)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.ls?4(dirname="")
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.mkdir?4(dirname)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.put?4(hostFileName, deviceFileName=None)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.putData?4(deviceFileName, content)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.pwd?4()
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.removeCredentials?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.rm?4(filename)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.rmdir?4(dirname)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.rmrf?4(name, recursive=False, force=False)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.runScript?4(script)
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.scanNetworks?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.selectDeviceDirectory?4(deviceDirectories)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.sendCommands?4(commandsList)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.setButtons?4()
@@ -2634,8 +2655,11 @@
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.setFileManager?4(on)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.setPlotter?4(on)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.setRepl?4(on)
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.startAccessPoint?4(ssid, security=None, password=None, ifconfig=None)
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.stopAccessPoint?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.supportsLocalFileAccess?4()
 eric7.MicroPython.Devices.DeviceBase.BaseDevice.syncTime?4(deviceType, hasCPy=False)
+eric7.MicroPython.Devices.DeviceBase.BaseDevice.writeCredentials?4(ssid, password)
 eric7.MicroPython.Devices.DeviceBase.BaseDevice?1(microPythonWidget, deviceType, parent=None)
 eric7.MicroPython.Devices.EspDevices.EspDevice._getSetTimeCode?5()
 eric7.MicroPython.Devices.EspDevices.EspDevice.addDeviceMenuEntries?4(menu)
@@ -2643,13 +2667,25 @@
 eric7.MicroPython.Devices.EspDevices.EspDevice.canStartFileManager?4()
 eric7.MicroPython.Devices.EspDevices.EspDevice.canStartPlotter?4()
 eric7.MicroPython.Devices.EspDevices.EspDevice.canStartRepl?4()
+eric7.MicroPython.Devices.EspDevices.EspDevice.checkInternet?4()
+eric7.MicroPython.Devices.EspDevices.EspDevice.connectWifi?4(ssid, password)
+eric7.MicroPython.Devices.EspDevices.EspDevice.deactivateInterface?4(interface)
 eric7.MicroPython.Devices.EspDevices.EspDevice.deviceName?4()
+eric7.MicroPython.Devices.EspDevices.EspDevice.disconnectWifi?4()
 eric7.MicroPython.Devices.EspDevices.EspDevice.forceInterrupt?4()
+eric7.MicroPython.Devices.EspDevices.EspDevice.getConnectedClients?4()
 eric7.MicroPython.Devices.EspDevices.EspDevice.getDocumentationUrl?4()
 eric7.MicroPython.Devices.EspDevices.EspDevice.getFirmwareUrl?4()
+eric7.MicroPython.Devices.EspDevices.EspDevice.getWifiData?4()
 eric7.MicroPython.Devices.EspDevices.EspDevice.hasFlashMenuEntry?4()
+eric7.MicroPython.Devices.EspDevices.EspDevice.hasWifi?4()
+eric7.MicroPython.Devices.EspDevices.EspDevice.removeCredentials?4()
 eric7.MicroPython.Devices.EspDevices.EspDevice.runScript?4(script)
+eric7.MicroPython.Devices.EspDevices.EspDevice.scanNetworks?4()
 eric7.MicroPython.Devices.EspDevices.EspDevice.setButtons?4()
+eric7.MicroPython.Devices.EspDevices.EspDevice.startAccessPoint?4(ssid, security=None, password=None, ifconfig=None)
+eric7.MicroPython.Devices.EspDevices.EspDevice.stopAccessPoint?4()
+eric7.MicroPython.Devices.EspDevices.EspDevice.writeCredentials?4(ssid, password)
 eric7.MicroPython.Devices.EspDevices.EspDevice?1(microPythonWidget, deviceType, parent=None)
 eric7.MicroPython.Devices.EspDevices.createDevice?4(microPythonWidget, deviceType, vid, pid, boardName, serialNumber)
 eric7.MicroPython.Devices.EspDialogs.EspBackupRestoreFirmwareDialog.EspBackupRestoreFirmwareDialog.Chips?7
@@ -2681,6 +2717,8 @@
 eric7.MicroPython.Devices.GenericMicroPythonDevices.GenericMicroPythonDevice?1(microPythonWidget, deviceType, vid, pid, parent=None)
 eric7.MicroPython.Devices.GenericMicroPythonDevices.createDevice?4(microPythonWidget, deviceType, vid, pid, boardName, serialNumber)
 eric7.MicroPython.Devices.IgnoredBoards?7
+eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect.connectWiFi?4()
+eric7.MicroPython.Devices.MCUScripts.picowWiFiConnect.connectWiFi?4()
 eric7.MicroPython.Devices.MicrobitDevices.MicrobitDevice._getSetTimeCode?5()
 eric7.MicroPython.Devices.MicrobitDevices.MicrobitDevice.addDeviceMenuEntries?4(menu)
 eric7.MicroPython.Devices.MicrobitDevices.MicrobitDevice.canRunScript?4()
@@ -2721,17 +2759,30 @@
 eric7.MicroPython.Devices.PyBoardDevices.createDevice?4(microPythonWidget, deviceType, vid, pid, boardName, serialNumber)
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device._getSetTimeCode?5()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.addDeviceMenuEntries?4(menu)
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.addDeviceWifiEntries?4(menu)
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.canRunScript?4()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.canStartFileManager?4()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.canStartPlotter?4()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.canStartRepl?4()
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.checkInternet?4()
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.connectWifi?4(ssid, password)
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.deactivateInterface?4(interface)
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.deviceName?4()
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.disconnectWifi?4()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.forceInterrupt?4()
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.getConnectedClients?4()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.getDocumentationUrl?4()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.getDownloadMenuEntries?4()
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.getWifiData?4()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.hasFlashMenuEntry?4()
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.hasWifi?4()
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.removeCredentials?4()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.runScript?4(script)
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.scanNetworks?4()
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device.setButtons?4()
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.startAccessPoint?4(ssid, security=None, password=None, ifconfig=None)
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.stopAccessPoint?4()
+eric7.MicroPython.Devices.RP2040Devices.RP2040Device.writeCredentials?4(ssid, password)
 eric7.MicroPython.Devices.RP2040Devices.RP2040Device?1(microPythonWidget, deviceType, parent=None)
 eric7.MicroPython.Devices.RP2040Devices.createDevice?4(microPythonWidget, deviceType, vid, pid, boardName, serialNumber)
 eric7.MicroPython.Devices.SupportedBoards?7
@@ -2755,12 +2806,15 @@
 eric7.MicroPython.Devices.getSupportedDevices?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.dataReceived?7
 eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.disconnectFromDevice?4()
-eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.execute?4(commands)
+eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.execute?4(commands, *, mode="raw", timeout=0)
 eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.executeAsync?4(commandsList)
 eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.executeAsyncFinished?7
+eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.executeAsyncPaste?4(commandsList)
 eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.handlePreferencesChanged?4()
 eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.isConnected?4()
 eric7.MicroPython.MicroPythonDeviceInterface.MicroPythonDeviceInterface.probeDevice?4()
@@ -2836,7 +2890,7 @@
 eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort.hasTimedOut?4()
 eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort.isConnected?4()
 eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort.openSerialLink?4(port)
-eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort.readUntil?4(expected=b"\n", size=None)
+eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort.readUntil?4(expected=b"\n", size=None, timeout=0)
 eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort.setTimeout?4(timeout)
 eric7.MicroPython.MicroPythonSerialPort.MicroPythonSerialPort?1(timeout=10000, parent=None)
 eric7.MicroPython.MicroPythonWidget.AnsiColorSchemes?7
@@ -2855,6 +2909,7 @@
 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()
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.handleDataFlood?4()
 eric7.MicroPython.MicroPythonWidget.MicroPythonWidget.isConnected?4()
@@ -2895,6 +2950,25 @@
 eric7.MicroPython.UnknownDevicesDialog.UnknownDevicesDialog.on_reportButton_clicked?4()
 eric7.MicroPython.UnknownDevicesDialog.UnknownDevicesDialog.on_restoreButton_clicked?4()
 eric7.MicroPython.UnknownDevicesDialog.UnknownDevicesDialog?1(parent=None)
+eric7.MicroPython.WifiDialogs.WifiApConfigDialog.WifiApConfigDialog.getApConfig?4()
+eric7.MicroPython.WifiDialogs.WifiApConfigDialog.WifiApConfigDialog.on_apShowPasswordButton_clicked?4(checked)
+eric7.MicroPython.WifiDialogs.WifiApConfigDialog.WifiApConfigDialog?1(withIP, parent=None)
+eric7.MicroPython.WifiDialogs.WifiApStationsDialog.WifiApStationsDialog?1(stations, parent=None)
+eric7.MicroPython.WifiDialogs.WifiConnectionDialog.WifiConnectionDialog.getConnectionParameters?4()
+eric7.MicroPython.WifiDialogs.WifiConnectionDialog.WifiConnectionDialog.on_showPasswordButton_clicked?4(checked)
+eric7.MicroPython.WifiDialogs.WifiConnectionDialog.WifiConnectionDialog.on_ssidEdit_textChanged?4(ssid)
+eric7.MicroPython.WifiDialogs.WifiConnectionDialog.WifiConnectionDialog?1(parent=None)
+eric7.MicroPython.WifiDialogs.WifiController.WifiController.createMenu?4(menu)
+eric7.MicroPython.WifiDialogs.WifiController.WifiController?1(microPython, parent=None)
+eric7.MicroPython.WifiDialogs.WifiCountryDialog.WifiCountryDialog.getCountry?4()
+eric7.MicroPython.WifiDialogs.WifiCountryDialog.WifiCountryDialog.on_countryEdit_textChanged?4(country)
+eric7.MicroPython.WifiDialogs.WifiCountryDialog.WifiCountryDialog?1(parent=None)
+eric7.MicroPython.WifiDialogs.WifiNetworksWindow.WifiNetworksWindow.closeEvent?4(evt)
+eric7.MicroPython.WifiDialogs.WifiNetworksWindow.WifiNetworksWindow.on_intervalSpinBox_valueChanged?4(interval)
+eric7.MicroPython.WifiDialogs.WifiNetworksWindow.WifiNetworksWindow.on_periodicCheckBox_toggled?4(checked)
+eric7.MicroPython.WifiDialogs.WifiNetworksWindow.WifiNetworksWindow.scanNetworks?4()
+eric7.MicroPython.WifiDialogs.WifiNetworksWindow.WifiNetworksWindow?1(device, parent=None)
+eric7.MicroPython.WifiDialogs.WifiStatusDialog.WifiStatusDialog?1(clientStatus, apStatus, overallStatus, parent=None)
 eric7.MultiProject.AddProjectDialog.AddProjectDialog.getData?4()
 eric7.MultiProject.AddProjectDialog.AddProjectDialog.on_filenamePicker_textChanged?4(txt)
 eric7.MultiProject.AddProjectDialog.AddProjectDialog.on_nameEdit_textChanged?4(txt)
@@ -7296,6 +7370,8 @@
 eric7.Preferences.ConfigurationPages.MasterPasswordEntryDialog.MasterPasswordEntryDialog.on_newPasswordAgainEdit_textChanged?4(txt)
 eric7.Preferences.ConfigurationPages.MasterPasswordEntryDialog.MasterPasswordEntryDialog.on_newPasswordEdit_textChanged?4(txt)
 eric7.Preferences.ConfigurationPages.MasterPasswordEntryDialog.MasterPasswordEntryDialog?1(oldPasswordHash, parent=None)
+eric7.Preferences.ConfigurationPages.MicroPythonPage.MicroPythonPage.on_apShowPasswordButton_clicked?4(checked)
+eric7.Preferences.ConfigurationPages.MicroPythonPage.MicroPythonPage.on_showPasswordButton_clicked?4(checked)
 eric7.Preferences.ConfigurationPages.MicroPythonPage.MicroPythonPage.save?4()
 eric7.Preferences.ConfigurationPages.MicroPythonPage.MicroPythonPage?1(parent=None)
 eric7.Preferences.ConfigurationPages.MicroPythonPage.create?4(dlg)
--- a/src/eric7/APIs/Python3/eric7.bas	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/APIs/Python3/eric7.bas	Fri Mar 03 11:31:53 2023 +0100
@@ -240,6 +240,7 @@
 EricGoogleMail QObject
 EricGraphicsView QGraphicsView
 EricHorizontalToolBox EricTabWidget
+EricIPv4InputWidget QWidget Ui_EricIPv4InputWidget
 EricIconBar QWidget
 EricJsonReader QTcpServer
 EricJsonServer QTcpServer
@@ -1123,6 +1124,13 @@
 WebInspector QWebEngineView
 WidgetArea QMdiArea
 WidgetView QWidget
+WifiApConfigDialog QDialog Ui_WifiApConfigDialog
+WifiApStationsDialog QDialog Ui_WifiApStationsDialog
+WifiConnectionDialog QDialog Ui_WifiConnectionDialog
+WifiController QObject
+WifiCountryDialog QDialog Ui_WifiCountryDialog
+WifiNetworksWindow QWidget Ui_WifiNetworksWindow
+WifiStatusDialog QDialog Ui_WifiStatusDialog
 WizardEricPluginWizard QObject
 XMLStreamReaderBase QXmlStreamReader
 XbelImporter BookmarksImporter
--- a/src/eric7/Documentation/Help/source.qhp	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Help/source.qhp	Fri Mar 03 11:31:53 2023 +0100
@@ -126,6 +126,7 @@
             <section title="eric7.EricNetwork.EricFtp" ref="eric7.EricNetwork.EricFtp.html" />
             <section title="eric7.EricNetwork.EricGoogleMail" ref="eric7.EricNetwork.EricGoogleMail.html" />
             <section title="eric7.EricNetwork.EricGoogleMailHelpers" ref="eric7.EricNetwork.EricGoogleMailHelpers.html" />
+            <section title="eric7.EricNetwork.EricIPv4InputWidget" ref="eric7.EricNetwork.EricIPv4InputWidget.html" />
             <section title="eric7.EricNetwork.EricJsonClient" ref="eric7.EricNetwork.EricJsonClient.html" />
             <section title="eric7.EricNetwork.EricJsonServer" ref="eric7.EricNetwork.EricJsonServer.html" />
             <section title="eric7.EricNetwork.EricJsonStreamReader" ref="eric7.EricNetwork.EricJsonStreamReader.html" />
@@ -280,6 +281,10 @@
                 <section title="eric7.MicroPython.Devices.EspDialogs.EspBackupRestoreFirmwareDialog" ref="eric7.MicroPython.Devices.EspDialogs.EspBackupRestoreFirmwareDialog.html" />
                 <section title="eric7.MicroPython.Devices.EspDialogs.EspFirmwareSelectionDialog" ref="eric7.MicroPython.Devices.EspDialogs.EspFirmwareSelectionDialog.html" />
               </section>
+              <section title="eric7.MicroPython.Devices.MCUScripts" ref="index-eric7.MicroPython.Devices.MCUScripts.html">
+                <section title="eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect" ref="eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect.html" />
+                <section title="eric7.MicroPython.Devices.MCUScripts.picowWiFiConnect" ref="eric7.MicroPython.Devices.MCUScripts.picowWiFiConnect.html" />
+              </section>
               <section title="eric7.MicroPython.Devices.CircuitPythonDevices" ref="eric7.MicroPython.Devices.CircuitPythonDevices.html" />
               <section title="eric7.MicroPython.Devices.DeviceBase" ref="eric7.MicroPython.Devices.DeviceBase.html" />
               <section title="eric7.MicroPython.Devices.EspDevices" ref="eric7.MicroPython.Devices.EspDevices.html" />
@@ -290,6 +295,15 @@
               <section title="eric7.MicroPython.Devices.TeensyDevices" ref="eric7.MicroPython.Devices.TeensyDevices.html" />
               <section title="eric7.MicroPython.Devices.__init__" ref="eric7.MicroPython.Devices.__init__.html" />
             </section>
+            <section title="eric7.MicroPython.WifiDialogs" ref="index-eric7.MicroPython.WifiDialogs.html">
+              <section title="eric7.MicroPython.WifiDialogs.WifiApConfigDialog" ref="eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html" />
+              <section title="eric7.MicroPython.WifiDialogs.WifiApStationsDialog" ref="eric7.MicroPython.WifiDialogs.WifiApStationsDialog.html" />
+              <section title="eric7.MicroPython.WifiDialogs.WifiConnectionDialog" ref="eric7.MicroPython.WifiDialogs.WifiConnectionDialog.html" />
+              <section title="eric7.MicroPython.WifiDialogs.WifiController" ref="eric7.MicroPython.WifiDialogs.WifiController.html" />
+              <section title="eric7.MicroPython.WifiDialogs.WifiCountryDialog" ref="eric7.MicroPython.WifiDialogs.WifiCountryDialog.html" />
+              <section title="eric7.MicroPython.WifiDialogs.WifiNetworksWindow" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html" />
+              <section title="eric7.MicroPython.WifiDialogs.WifiStatusDialog" ref="eric7.MicroPython.WifiDialogs.WifiStatusDialog.html" />
+            </section>
             <section title="eric7.MicroPython.AddEditDevicesDialog" ref="eric7.MicroPython.AddEditDevicesDialog.html" />
             <section title="eric7.MicroPython.BoardDataDialog" ref="eric7.MicroPython.BoardDataDialog.html" />
             <section title="eric7.MicroPython.ConnectionSelectionDialog" ref="eric7.MicroPython.ConnectionSelectionDialog.html" />
@@ -2048,18 +2062,24 @@
       <keyword name="BaseDevice._getSetTimeCode" id="BaseDevice._getSetTimeCode" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice._getSetTimeCode" />
       <keyword name="BaseDevice._shortError" id="BaseDevice._shortError" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice._shortError" />
       <keyword name="BaseDevice.addDeviceMenuEntries" id="BaseDevice.addDeviceMenuEntries" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.addDeviceMenuEntries" />
+      <keyword name="BaseDevice.addDeviceWifiEntries" id="BaseDevice.addDeviceWifiEntries" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.addDeviceWifiEntries" />
       <keyword name="BaseDevice.canRunScript" id="BaseDevice.canRunScript" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.canRunScript" />
       <keyword name="BaseDevice.canStartFileManager" id="BaseDevice.canStartFileManager" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.canStartFileManager" />
       <keyword name="BaseDevice.canStartPlotter" id="BaseDevice.canStartPlotter" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.canStartPlotter" />
       <keyword name="BaseDevice.canStartRepl" id="BaseDevice.canStartRepl" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.canStartRepl" />
       <keyword name="BaseDevice.cd" id="BaseDevice.cd" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.cd" />
       <keyword name="BaseDevice.checkDeviceData" id="BaseDevice.checkDeviceData" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.checkDeviceData" />
+      <keyword name="BaseDevice.checkInternet" id="BaseDevice.checkInternet" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.checkInternet" />
+      <keyword name="BaseDevice.connectWifi" id="BaseDevice.connectWifi" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.connectWifi" />
+      <keyword name="BaseDevice.deactivateInterface" id="BaseDevice.deactivateInterface" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.deactivateInterface" />
       <keyword name="BaseDevice.deviceName" id="BaseDevice.deviceName" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.deviceName" />
+      <keyword name="BaseDevice.disconnectWifi" id="BaseDevice.disconnectWifi" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.disconnectWifi" />
       <keyword name="BaseDevice.downloadFirmware" id="BaseDevice.downloadFirmware" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.downloadFirmware" />
       <keyword name="BaseDevice.fileSystemInfo" id="BaseDevice.fileSystemInfo" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.fileSystemInfo" />
       <keyword name="BaseDevice.forceInterrupt" id="BaseDevice.forceInterrupt" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.forceInterrupt" />
       <keyword name="BaseDevice.get" id="BaseDevice.get" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.get" />
       <keyword name="BaseDevice.getBoardInformation" id="BaseDevice.getBoardInformation" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getBoardInformation" />
+      <keyword name="BaseDevice.getConnectedClients" id="BaseDevice.getConnectedClients" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getConnectedClients" />
       <keyword name="BaseDevice.getData" id="BaseDevice.getData" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getData" />
       <keyword name="BaseDevice.getDeviceData" id="BaseDevice.getDeviceData" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getDeviceData" />
       <keyword name="BaseDevice.getDeviceType" id="BaseDevice.getDeviceType" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getDeviceType" />
@@ -2068,23 +2088,29 @@
       <keyword name="BaseDevice.getFirmwareUrl" id="BaseDevice.getFirmwareUrl" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getFirmwareUrl" />
       <keyword name="BaseDevice.getModules" id="BaseDevice.getModules" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getModules" />
       <keyword name="BaseDevice.getTime" id="BaseDevice.getTime" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getTime" />
+      <keyword name="BaseDevice.getWifiData" id="BaseDevice.getWifiData" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getWifiData" />
       <keyword name="BaseDevice.getWorkspace" id="BaseDevice.getWorkspace" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.getWorkspace" />
       <keyword name="BaseDevice.handleDataFlood" id="BaseDevice.handleDataFlood" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.handleDataFlood" />
+      <keyword name="BaseDevice.hasBluetooth" id="BaseDevice.hasBluetooth" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.hasBluetooth" />
       <keyword name="BaseDevice.hasCircuitPython" id="BaseDevice.hasCircuitPython" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.hasCircuitPython" />
       <keyword name="BaseDevice.hasDocumentationUrl" id="BaseDevice.hasDocumentationUrl" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.hasDocumentationUrl" />
+      <keyword name="BaseDevice.hasEthernet" id="BaseDevice.hasEthernet" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.hasEthernet" />
       <keyword name="BaseDevice.hasFirmwareUrl" id="BaseDevice.hasFirmwareUrl" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.hasFirmwareUrl" />
       <keyword name="BaseDevice.hasFlashMenuEntry" id="BaseDevice.hasFlashMenuEntry" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.hasFlashMenuEntry" />
       <keyword name="BaseDevice.hasTimeCommands" id="BaseDevice.hasTimeCommands" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.hasTimeCommands" />
+      <keyword name="BaseDevice.hasWifi" id="BaseDevice.hasWifi" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.hasWifi" />
       <keyword name="BaseDevice.lls" id="BaseDevice.lls" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.lls" />
       <keyword name="BaseDevice.ls" id="BaseDevice.ls" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.ls" />
       <keyword name="BaseDevice.mkdir" id="BaseDevice.mkdir" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.mkdir" />
       <keyword name="BaseDevice.put" id="BaseDevice.put" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.put" />
       <keyword name="BaseDevice.putData" id="BaseDevice.putData" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.putData" />
       <keyword name="BaseDevice.pwd" id="BaseDevice.pwd" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.pwd" />
+      <keyword name="BaseDevice.removeCredentials" id="BaseDevice.removeCredentials" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.removeCredentials" />
       <keyword name="BaseDevice.rm" id="BaseDevice.rm" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.rm" />
       <keyword name="BaseDevice.rmdir" id="BaseDevice.rmdir" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.rmdir" />
       <keyword name="BaseDevice.rmrf" id="BaseDevice.rmrf" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.rmrf" />
       <keyword name="BaseDevice.runScript" id="BaseDevice.runScript" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.runScript" />
+      <keyword name="BaseDevice.scanNetworks" id="BaseDevice.scanNetworks" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.scanNetworks" />
       <keyword name="BaseDevice.selectDeviceDirectory" id="BaseDevice.selectDeviceDirectory" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.selectDeviceDirectory" />
       <keyword name="BaseDevice.sendCommands" id="BaseDevice.sendCommands" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.sendCommands" />
       <keyword name="BaseDevice.setButtons" id="BaseDevice.setButtons" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.setButtons" />
@@ -2092,8 +2118,11 @@
       <keyword name="BaseDevice.setFileManager" id="BaseDevice.setFileManager" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.setFileManager" />
       <keyword name="BaseDevice.setPlotter" id="BaseDevice.setPlotter" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.setPlotter" />
       <keyword name="BaseDevice.setRepl" id="BaseDevice.setRepl" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.setRepl" />
+      <keyword name="BaseDevice.startAccessPoint" id="BaseDevice.startAccessPoint" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.startAccessPoint" />
+      <keyword name="BaseDevice.stopAccessPoint" id="BaseDevice.stopAccessPoint" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.stopAccessPoint" />
       <keyword name="BaseDevice.supportsLocalFileAccess" id="BaseDevice.supportsLocalFileAccess" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.supportsLocalFileAccess" />
       <keyword name="BaseDevice.syncTime" id="BaseDevice.syncTime" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.syncTime" />
+      <keyword name="BaseDevice.writeCredentials" id="BaseDevice.writeCredentials" ref="eric7.MicroPython.Devices.DeviceBase.html#BaseDevice.writeCredentials" />
       <keyword name="BaseDocstringGenerator" id="BaseDocstringGenerator" ref="eric7.QScintilla.DocstringGenerator.BaseDocstringGenerator.html#BaseDocstringGenerator" />
       <keyword name="BaseDocstringGenerator (Constructor)" id="BaseDocstringGenerator (Constructor)" ref="eric7.QScintilla.DocstringGenerator.BaseDocstringGenerator.html#BaseDocstringGenerator.__init__" />
       <keyword name="BaseDocstringGenerator (Module)" id="BaseDocstringGenerator (Module)" ref="eric7.QScintilla.DocstringGenerator.BaseDocstringGenerator.html" />
@@ -5213,6 +5242,17 @@
       <keyword name="EricHorizontalToolBox.removeItem" id="EricHorizontalToolBox.removeItem" ref="eric7.EricWidgets.EricToolBox.html#EricHorizontalToolBox.removeItem" />
       <keyword name="EricHorizontalToolBox.setItemEnabled" id="EricHorizontalToolBox.setItemEnabled" ref="eric7.EricWidgets.EricToolBox.html#EricHorizontalToolBox.setItemEnabled" />
       <keyword name="EricHorizontalToolBox.setItemToolTip" id="EricHorizontalToolBox.setItemToolTip" ref="eric7.EricWidgets.EricToolBox.html#EricHorizontalToolBox.setItemToolTip" />
+      <keyword name="EricIPv4InputWidget" id="EricIPv4InputWidget" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget" />
+      <keyword name="EricIPv4InputWidget (Constructor)" id="EricIPv4InputWidget (Constructor)" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget.__init__" />
+      <keyword name="EricIPv4InputWidget (Module)" id="EricIPv4InputWidget (Module)" ref="eric7.EricNetwork.EricIPv4InputWidget.html" />
+      <keyword name="EricIPv4InputWidget.__clear" id="EricIPv4InputWidget.__clear" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget.__clear" />
+      <keyword name="EricIPv4InputWidget.address" id="EricIPv4InputWidget.address" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget.address" />
+      <keyword name="EricIPv4InputWidget.clear" id="EricIPv4InputWidget.clear" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget.clear" />
+      <keyword name="EricIPv4InputWidget.eventFilter" id="EricIPv4InputWidget.eventFilter" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget.eventFilter" />
+      <keyword name="EricIPv4InputWidget.hasAcceptableInput" id="EricIPv4InputWidget.hasAcceptableInput" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget.hasAcceptableInput" />
+      <keyword name="EricIPv4InputWidget.setAddress" id="EricIPv4InputWidget.setAddress" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget.setAddress" />
+      <keyword name="EricIPv4InputWidget.setText" id="EricIPv4InputWidget.setText" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget.setText" />
+      <keyword name="EricIPv4InputWidget.text" id="EricIPv4InputWidget.text" ref="eric7.EricNetwork.EricIPv4InputWidget.html#EricIPv4InputWidget.text" />
       <keyword name="EricIconBar" id="EricIconBar" ref="eric7.EricWidgets.EricIconBar.html#EricIconBar" />
       <keyword name="EricIconBar (Constructor)" id="EricIconBar (Constructor)" ref="eric7.EricWidgets.EricIconBar.html#EricIconBar.__init__" />
       <keyword name="EricIconBar (Module)" id="EricIconBar (Module)" ref="eric7.EricWidgets.EricIconBar.html" />
@@ -6132,13 +6172,25 @@
       <keyword name="EspDevice.canStartFileManager" id="EspDevice.canStartFileManager" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.canStartFileManager" />
       <keyword name="EspDevice.canStartPlotter" id="EspDevice.canStartPlotter" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.canStartPlotter" />
       <keyword name="EspDevice.canStartRepl" id="EspDevice.canStartRepl" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.canStartRepl" />
+      <keyword name="EspDevice.checkInternet" id="EspDevice.checkInternet" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.checkInternet" />
+      <keyword name="EspDevice.connectWifi" id="EspDevice.connectWifi" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.connectWifi" />
+      <keyword name="EspDevice.deactivateInterface" id="EspDevice.deactivateInterface" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.deactivateInterface" />
       <keyword name="EspDevice.deviceName" id="EspDevice.deviceName" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.deviceName" />
+      <keyword name="EspDevice.disconnectWifi" id="EspDevice.disconnectWifi" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.disconnectWifi" />
       <keyword name="EspDevice.forceInterrupt" id="EspDevice.forceInterrupt" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.forceInterrupt" />
+      <keyword name="EspDevice.getConnectedClients" id="EspDevice.getConnectedClients" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.getConnectedClients" />
       <keyword name="EspDevice.getDocumentationUrl" id="EspDevice.getDocumentationUrl" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.getDocumentationUrl" />
       <keyword name="EspDevice.getFirmwareUrl" id="EspDevice.getFirmwareUrl" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.getFirmwareUrl" />
+      <keyword name="EspDevice.getWifiData" id="EspDevice.getWifiData" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.getWifiData" />
       <keyword name="EspDevice.hasFlashMenuEntry" id="EspDevice.hasFlashMenuEntry" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.hasFlashMenuEntry" />
+      <keyword name="EspDevice.hasWifi" id="EspDevice.hasWifi" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.hasWifi" />
+      <keyword name="EspDevice.removeCredentials" id="EspDevice.removeCredentials" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.removeCredentials" />
       <keyword name="EspDevice.runScript" id="EspDevice.runScript" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.runScript" />
+      <keyword name="EspDevice.scanNetworks" id="EspDevice.scanNetworks" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.scanNetworks" />
       <keyword name="EspDevice.setButtons" id="EspDevice.setButtons" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.setButtons" />
+      <keyword name="EspDevice.startAccessPoint" id="EspDevice.startAccessPoint" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.startAccessPoint" />
+      <keyword name="EspDevice.stopAccessPoint" id="EspDevice.stopAccessPoint" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.stopAccessPoint" />
+      <keyword name="EspDevice.writeCredentials" id="EspDevice.writeCredentials" ref="eric7.MicroPython.Devices.EspDevices.html#EspDevice.writeCredentials" />
       <keyword name="EspDevices (Module)" id="EspDevices (Module)" ref="eric7.MicroPython.Devices.EspDevices.html" />
       <keyword name="EspDialogs (Package)" id="EspDialogs (Package)" ref="index-eric7.MicroPython.Devices.EspDialogs.html" />
       <keyword name="EspFirmwareSelectionDialog" id="EspFirmwareSelectionDialog" ref="eric7.MicroPython.Devices.EspDialogs.EspFirmwareSelectionDialog.html#EspFirmwareSelectionDialog" />
@@ -10430,6 +10482,7 @@
       <keyword name="M520NameFinder.visit_Lambda" id="M520NameFinder.visit_Lambda" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Miscellaneous.MiscellaneousChecker.html#M520NameFinder.visit_Lambda" />
       <keyword name="M520NameFinder.visit_ListComp" id="M520NameFinder.visit_ListComp" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Miscellaneous.MiscellaneousChecker.html#M520NameFinder.visit_ListComp" />
       <keyword name="M520NameFinder.visit_comprehension" id="M520NameFinder.visit_comprehension" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Miscellaneous.MiscellaneousChecker.html#M520NameFinder.visit_comprehension" />
+      <keyword name="MCUScripts (Package)" id="MCUScripts (Package)" ref="index-eric7.MicroPython.Devices.MCUScripts.html" />
       <keyword name="MakePropertiesDialog" id="MakePropertiesDialog" ref="eric7.Project.MakePropertiesDialog.html#MakePropertiesDialog" />
       <keyword name="MakePropertiesDialog (Constructor)" id="MakePropertiesDialog (Constructor)" ref="eric7.Project.MakePropertiesDialog.html#MakePropertiesDialog.__init__" />
       <keyword name="MakePropertiesDialog (Module)" id="MakePropertiesDialog (Module)" ref="eric7.Project.MakePropertiesDialog.html" />
@@ -10564,6 +10617,10 @@
       <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.__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" />
@@ -10571,6 +10628,7 @@
       <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" />
       <keyword name="MicroPythonDeviceInterface.executeAsync" id="MicroPythonDeviceInterface.executeAsync" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.executeAsync" />
+      <keyword name="MicroPythonDeviceInterface.executeAsyncPaste" id="MicroPythonDeviceInterface.executeAsyncPaste" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.executeAsyncPaste" />
       <keyword name="MicroPythonDeviceInterface.handlePreferencesChanged" id="MicroPythonDeviceInterface.handlePreferencesChanged" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.handlePreferencesChanged" />
       <keyword name="MicroPythonDeviceInterface.isConnected" id="MicroPythonDeviceInterface.isConnected" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.isConnected" />
       <keyword name="MicroPythonDeviceInterface.probeDevice" id="MicroPythonDeviceInterface.probeDevice" ref="eric7.MicroPython.MicroPythonDeviceInterface.html#MicroPythonDeviceInterface.probeDevice" />
@@ -10656,6 +10714,8 @@
       <keyword name="MicroPythonPage" id="MicroPythonPage" ref="eric7.Preferences.ConfigurationPages.MicroPythonPage.html#MicroPythonPage" />
       <keyword name="MicroPythonPage (Constructor)" id="MicroPythonPage (Constructor)" ref="eric7.Preferences.ConfigurationPages.MicroPythonPage.html#MicroPythonPage.__init__" />
       <keyword name="MicroPythonPage (Module)" id="MicroPythonPage (Module)" ref="eric7.Preferences.ConfigurationPages.MicroPythonPage.html" />
+      <keyword name="MicroPythonPage.on_apShowPasswordButton_clicked" id="MicroPythonPage.on_apShowPasswordButton_clicked" ref="eric7.Preferences.ConfigurationPages.MicroPythonPage.html#MicroPythonPage.on_apShowPasswordButton_clicked" />
+      <keyword name="MicroPythonPage.on_showPasswordButton_clicked" id="MicroPythonPage.on_showPasswordButton_clicked" ref="eric7.Preferences.ConfigurationPages.MicroPythonPage.html#MicroPythonPage.on_showPasswordButton_clicked" />
       <keyword name="MicroPythonPage.save" id="MicroPythonPage.save" ref="eric7.Preferences.ConfigurationPages.MicroPythonPage.html#MicroPythonPage.save" />
       <keyword name="MicroPythonProgressInfoDialog" id="MicroPythonProgressInfoDialog" ref="eric7.MicroPython.MicroPythonProgressInfoDialog.html#MicroPythonProgressInfoDialog" />
       <keyword name="MicroPythonProgressInfoDialog (Constructor)" id="MicroPythonProgressInfoDialog (Constructor)" ref="eric7.MicroPython.MicroPythonProgressInfoDialog.html#MicroPythonProgressInfoDialog.__init__" />
@@ -10703,7 +10763,6 @@
       <keyword name="MicroPythonWidget.__showDeviceTime" id="MicroPythonWidget.__showDeviceTime" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.__showDeviceTime" />
       <keyword name="MicroPythonWidget.__showDeviceVersion" id="MicroPythonWidget.__showDeviceVersion" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.__showDeviceVersion" />
       <keyword name="MicroPythonWidget.__showDocumentation" id="MicroPythonWidget.__showDocumentation" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.__showDocumentation" />
-      <keyword name="MicroPythonWidget.__showError" id="MicroPythonWidget.__showError" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.__showError" />
       <keyword name="MicroPythonWidget.__showImplementation" id="MicroPythonWidget.__showImplementation" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.__showImplementation" />
       <keyword name="MicroPythonWidget.__showLocalAndDeviceTime" id="MicroPythonWidget.__showLocalAndDeviceTime" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.__showLocalAndDeviceTime" />
       <keyword name="MicroPythonWidget.__showLocalTime" id="MicroPythonWidget.__showLocalTime" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.__showLocalTime" />
@@ -10714,6 +10773,7 @@
       <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" />
       <keyword name="MicroPythonWidget.handleDataFlood" id="MicroPythonWidget.handleDataFlood" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.handleDataFlood" />
       <keyword name="MicroPythonWidget.isConnected" id="MicroPythonWidget.isConnected" ref="eric7.MicroPython.MicroPythonWidget.html#MicroPythonWidget.isConnected" />
@@ -13653,20 +13713,34 @@
       <keyword name="RP2040Device.__createRP2040Menu" id="RP2040Device.__createRP2040Menu" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.__createRP2040Menu" />
       <keyword name="RP2040Device.__firmwareVersionResponse" id="RP2040Device.__firmwareVersionResponse" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.__firmwareVersionResponse" />
       <keyword name="RP2040Device.__flashPython" id="RP2040Device.__flashPython" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.__flashPython" />
+      <keyword name="RP2040Device.__setCountry" id="RP2040Device.__setCountry" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.__setCountry" />
       <keyword name="RP2040Device.__showFirmwareVersions" id="RP2040Device.__showFirmwareVersions" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.__showFirmwareVersions" />
       <keyword name="RP2040Device._getSetTimeCode" id="RP2040Device._getSetTimeCode" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device._getSetTimeCode" />
       <keyword name="RP2040Device.addDeviceMenuEntries" id="RP2040Device.addDeviceMenuEntries" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.addDeviceMenuEntries" />
+      <keyword name="RP2040Device.addDeviceWifiEntries" id="RP2040Device.addDeviceWifiEntries" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.addDeviceWifiEntries" />
       <keyword name="RP2040Device.canRunScript" id="RP2040Device.canRunScript" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.canRunScript" />
       <keyword name="RP2040Device.canStartFileManager" id="RP2040Device.canStartFileManager" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.canStartFileManager" />
       <keyword name="RP2040Device.canStartPlotter" id="RP2040Device.canStartPlotter" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.canStartPlotter" />
       <keyword name="RP2040Device.canStartRepl" id="RP2040Device.canStartRepl" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.canStartRepl" />
+      <keyword name="RP2040Device.checkInternet" id="RP2040Device.checkInternet" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.checkInternet" />
+      <keyword name="RP2040Device.connectWifi" id="RP2040Device.connectWifi" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.connectWifi" />
+      <keyword name="RP2040Device.deactivateInterface" id="RP2040Device.deactivateInterface" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.deactivateInterface" />
       <keyword name="RP2040Device.deviceName" id="RP2040Device.deviceName" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.deviceName" />
+      <keyword name="RP2040Device.disconnectWifi" id="RP2040Device.disconnectWifi" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.disconnectWifi" />
       <keyword name="RP2040Device.forceInterrupt" id="RP2040Device.forceInterrupt" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.forceInterrupt" />
+      <keyword name="RP2040Device.getConnectedClients" id="RP2040Device.getConnectedClients" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.getConnectedClients" />
       <keyword name="RP2040Device.getDocumentationUrl" id="RP2040Device.getDocumentationUrl" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.getDocumentationUrl" />
       <keyword name="RP2040Device.getDownloadMenuEntries" id="RP2040Device.getDownloadMenuEntries" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.getDownloadMenuEntries" />
+      <keyword name="RP2040Device.getWifiData" id="RP2040Device.getWifiData" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.getWifiData" />
       <keyword name="RP2040Device.hasFlashMenuEntry" id="RP2040Device.hasFlashMenuEntry" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.hasFlashMenuEntry" />
+      <keyword name="RP2040Device.hasWifi" id="RP2040Device.hasWifi" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.hasWifi" />
+      <keyword name="RP2040Device.removeCredentials" id="RP2040Device.removeCredentials" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.removeCredentials" />
       <keyword name="RP2040Device.runScript" id="RP2040Device.runScript" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.runScript" />
+      <keyword name="RP2040Device.scanNetworks" id="RP2040Device.scanNetworks" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.scanNetworks" />
       <keyword name="RP2040Device.setButtons" id="RP2040Device.setButtons" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.setButtons" />
+      <keyword name="RP2040Device.startAccessPoint" id="RP2040Device.startAccessPoint" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.startAccessPoint" />
+      <keyword name="RP2040Device.stopAccessPoint" id="RP2040Device.stopAccessPoint" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.stopAccessPoint" />
+      <keyword name="RP2040Device.writeCredentials" id="RP2040Device.writeCredentials" ref="eric7.MicroPython.Devices.RP2040Devices.html#RP2040Device.writeCredentials" />
       <keyword name="RP2040Devices (Module)" id="RP2040Devices (Module)" ref="eric7.MicroPython.Devices.RP2040Devices.html" />
       <keyword name="RbModule" id="RbModule" ref="eric7.Utilities.ModuleParser.html#RbModule" />
       <keyword name="RbModule (Constructor)" id="RbModule (Constructor)" ref="eric7.Utilities.ModuleParser.html#RbModule.__init__" />
@@ -18567,6 +18641,56 @@
       <keyword name="WidgetView.buildWidget" id="WidgetView.buildWidget" ref="eric7.Tools.TRPreviewer.html#WidgetView.buildWidget" />
       <keyword name="WidgetView.isValid" id="WidgetView.isValid" ref="eric7.Tools.TRPreviewer.html#WidgetView.isValid" />
       <keyword name="WidgetView.uiFileName" id="WidgetView.uiFileName" ref="eric7.Tools.TRPreviewer.html#WidgetView.uiFileName" />
+      <keyword name="WifiApConfigDialog" id="WifiApConfigDialog" ref="eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html#WifiApConfigDialog" />
+      <keyword name="WifiApConfigDialog (Constructor)" id="WifiApConfigDialog (Constructor)" ref="eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html#WifiApConfigDialog.__init__" />
+      <keyword name="WifiApConfigDialog (Module)" id="WifiApConfigDialog (Module)" ref="eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html" />
+      <keyword name="WifiApConfigDialog.__updateOk" id="WifiApConfigDialog.__updateOk" ref="eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html#WifiApConfigDialog.__updateOk" />
+      <keyword name="WifiApConfigDialog.getApConfig" id="WifiApConfigDialog.getApConfig" ref="eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html#WifiApConfigDialog.getApConfig" />
+      <keyword name="WifiApConfigDialog.on_apShowPasswordButton_clicked" id="WifiApConfigDialog.on_apShowPasswordButton_clicked" ref="eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html#WifiApConfigDialog.on_apShowPasswordButton_clicked" />
+      <keyword name="WifiApStationsDialog" id="WifiApStationsDialog" ref="eric7.MicroPython.WifiDialogs.WifiApStationsDialog.html#WifiApStationsDialog" />
+      <keyword name="WifiApStationsDialog (Constructor)" id="WifiApStationsDialog (Constructor)" ref="eric7.MicroPython.WifiDialogs.WifiApStationsDialog.html#WifiApStationsDialog.__init__" />
+      <keyword name="WifiApStationsDialog (Module)" id="WifiApStationsDialog (Module)" ref="eric7.MicroPython.WifiDialogs.WifiApStationsDialog.html" />
+      <keyword name="WifiConnectionDialog" id="WifiConnectionDialog" ref="eric7.MicroPython.WifiDialogs.WifiConnectionDialog.html#WifiConnectionDialog" />
+      <keyword name="WifiConnectionDialog (Constructor)" id="WifiConnectionDialog (Constructor)" ref="eric7.MicroPython.WifiDialogs.WifiConnectionDialog.html#WifiConnectionDialog.__init__" />
+      <keyword name="WifiConnectionDialog (Module)" id="WifiConnectionDialog (Module)" ref="eric7.MicroPython.WifiDialogs.WifiConnectionDialog.html" />
+      <keyword name="WifiConnectionDialog.getConnectionParameters" id="WifiConnectionDialog.getConnectionParameters" ref="eric7.MicroPython.WifiDialogs.WifiConnectionDialog.html#WifiConnectionDialog.getConnectionParameters" />
+      <keyword name="WifiConnectionDialog.on_showPasswordButton_clicked" id="WifiConnectionDialog.on_showPasswordButton_clicked" ref="eric7.MicroPython.WifiDialogs.WifiConnectionDialog.html#WifiConnectionDialog.on_showPasswordButton_clicked" />
+      <keyword name="WifiConnectionDialog.on_ssidEdit_textChanged" id="WifiConnectionDialog.on_ssidEdit_textChanged" ref="eric7.MicroPython.WifiDialogs.WifiConnectionDialog.html#WifiConnectionDialog.on_ssidEdit_textChanged" />
+      <keyword name="WifiController" id="WifiController" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController" />
+      <keyword name="WifiController (Constructor)" id="WifiController (Constructor)" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__init__" />
+      <keyword name="WifiController (Module)" id="WifiController (Module)" ref="eric7.MicroPython.WifiDialogs.WifiController.html" />
+      <keyword name="WifiController.__checkInternet" id="WifiController.__checkInternet" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__checkInternet" />
+      <keyword name="WifiController.__connectWifi" id="WifiController.__connectWifi" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__connectWifi" />
+      <keyword name="WifiController.__deactivateInterface" id="WifiController.__deactivateInterface" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__deactivateInterface" />
+      <keyword name="WifiController.__disconnectWifi" id="WifiController.__disconnectWifi" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__disconnectWifi" />
+      <keyword name="WifiController.__removeCredentials" id="WifiController.__removeCredentials" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__removeCredentials" />
+      <keyword name="WifiController.__scanNetwork" id="WifiController.__scanNetwork" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__scanNetwork" />
+      <keyword name="WifiController.__showConnectedClients" id="WifiController.__showConnectedClients" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__showConnectedClients" />
+      <keyword name="WifiController.__showWifiStatus" id="WifiController.__showWifiStatus" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__showWifiStatus" />
+      <keyword name="WifiController.__startAccessPoint" id="WifiController.__startAccessPoint" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__startAccessPoint" />
+      <keyword name="WifiController.__startAccessPointIP" id="WifiController.__startAccessPointIP" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__startAccessPointIP" />
+      <keyword name="WifiController.__stopAccessPoint" id="WifiController.__stopAccessPoint" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__stopAccessPoint" />
+      <keyword name="WifiController.__writeCredentials" id="WifiController.__writeCredentials" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.__writeCredentials" />
+      <keyword name="WifiController.createMenu" id="WifiController.createMenu" ref="eric7.MicroPython.WifiDialogs.WifiController.html#WifiController.createMenu" />
+      <keyword name="WifiCountryDialog" id="WifiCountryDialog" ref="eric7.MicroPython.WifiDialogs.WifiCountryDialog.html#WifiCountryDialog" />
+      <keyword name="WifiCountryDialog (Constructor)" id="WifiCountryDialog (Constructor)" ref="eric7.MicroPython.WifiDialogs.WifiCountryDialog.html#WifiCountryDialog.__init__" />
+      <keyword name="WifiCountryDialog (Module)" id="WifiCountryDialog (Module)" ref="eric7.MicroPython.WifiDialogs.WifiCountryDialog.html" />
+      <keyword name="WifiCountryDialog.getCountry" id="WifiCountryDialog.getCountry" ref="eric7.MicroPython.WifiDialogs.WifiCountryDialog.html#WifiCountryDialog.getCountry" />
+      <keyword name="WifiCountryDialog.on_countryEdit_textChanged" id="WifiCountryDialog.on_countryEdit_textChanged" ref="eric7.MicroPython.WifiDialogs.WifiCountryDialog.html#WifiCountryDialog.on_countryEdit_textChanged" />
+      <keyword name="WifiDialogs (Package)" id="WifiDialogs (Package)" ref="index-eric7.MicroPython.WifiDialogs.html" />
+      <keyword name="WifiNetworksWindow" id="WifiNetworksWindow" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html#WifiNetworksWindow" />
+      <keyword name="WifiNetworksWindow (Constructor)" id="WifiNetworksWindow (Constructor)" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html#WifiNetworksWindow.__init__" />
+      <keyword name="WifiNetworksWindow (Module)" id="WifiNetworksWindow (Module)" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html" />
+      <keyword name="WifiNetworksWindow.__resizeColumns" id="WifiNetworksWindow.__resizeColumns" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html#WifiNetworksWindow.__resizeColumns" />
+      <keyword name="WifiNetworksWindow.__resort" id="WifiNetworksWindow.__resort" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html#WifiNetworksWindow.__resort" />
+      <keyword name="WifiNetworksWindow.closeEvent" id="WifiNetworksWindow.closeEvent" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html#WifiNetworksWindow.closeEvent" />
+      <keyword name="WifiNetworksWindow.on_intervalSpinBox_valueChanged" id="WifiNetworksWindow.on_intervalSpinBox_valueChanged" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html#WifiNetworksWindow.on_intervalSpinBox_valueChanged" />
+      <keyword name="WifiNetworksWindow.on_periodicCheckBox_toggled" id="WifiNetworksWindow.on_periodicCheckBox_toggled" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html#WifiNetworksWindow.on_periodicCheckBox_toggled" />
+      <keyword name="WifiNetworksWindow.scanNetworks" id="WifiNetworksWindow.scanNetworks" ref="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html#WifiNetworksWindow.scanNetworks" />
+      <keyword name="WifiStatusDialog" id="WifiStatusDialog" ref="eric7.MicroPython.WifiDialogs.WifiStatusDialog.html#WifiStatusDialog" />
+      <keyword name="WifiStatusDialog (Constructor)" id="WifiStatusDialog (Constructor)" ref="eric7.MicroPython.WifiDialogs.WifiStatusDialog.html#WifiStatusDialog.__init__" />
+      <keyword name="WifiStatusDialog (Module)" id="WifiStatusDialog (Module)" ref="eric7.MicroPython.WifiDialogs.WifiStatusDialog.html" />
+      <keyword name="WifiStatusDialog.__createHeader" id="WifiStatusDialog.__createHeader" ref="eric7.MicroPython.WifiDialogs.WifiStatusDialog.html#WifiStatusDialog.__createHeader" />
       <keyword name="WizardEricPluginWizard" id="WizardEricPluginWizard" ref="eric7.Plugins.PluginWizardEricPlugin.html#WizardEricPluginWizard" />
       <keyword name="WizardEricPluginWizard (Constructor)" id="WizardEricPluginWizard (Constructor)" ref="eric7.Plugins.PluginWizardEricPlugin.html#WizardEricPluginWizard.__init__" />
       <keyword name="WizardEricPluginWizard.__callForm" id="WizardEricPluginWizard.__callForm" ref="eric7.Plugins.PluginWizardEricPlugin.html#WizardEricPluginWizard.__callForm" />
@@ -18913,6 +19037,8 @@
       <keyword name="condaVersionStr" id="condaVersionStr" ref="eric7.CondaInterface.__init__.html#condaVersionStr" />
       <keyword name="confirmOverwrite" id="confirmOverwrite" ref="eric7.EricWidgets.EricFileSaveConfirmDialog.html#confirmOverwrite" />
       <keyword name="conflicting_deps" id="conflicting_deps" ref="eric7.PipInterface.pipdeptree.html#conflicting_deps" />
+      <keyword name="connectWiFi" id="connectWiFi" ref="eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect.html#connectWiFi" />
+      <keyword name="connectWiFi" id="connectWiFi" ref="eric7.MicroPython.Devices.MCUScripts.picowWiFiConnect.html#connectWiFi" />
       <keyword name="containsSpace" id="containsSpace" ref="eric7.WebBrowser.Tools.WebBrowserTools.html#containsSpace" />
       <keyword name="continued_indentation" id="continued_indentation" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#continued_indentation" />
       <keyword name="convertLineEnds" id="convertLineEnds" ref="eric7.Utilities.__init__.html#convertLineEnds" />
@@ -19171,6 +19297,7 @@
       <keyword name="escape_entities" id="escape_entities" ref="eric7.Utilities.__init__.html#escape_entities" />
       <keyword name="escape_uentities" id="escape_uentities" ref="eric7.Utilities.__init__.html#escape_uentities" />
       <keyword name="escapedBytesRepresentation" id="escapedBytesRepresentation" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Security.SecurityUtils.html#escapedBytesRepresentation" />
+      <keyword name="esp32WiFiConnect (Module)" id="esp32WiFiConnect (Module)" ref="eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect.html" />
       <keyword name="evaluateCall" id="evaluateCall" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Security.Checks.djangoXssVulnerability.html#evaluateCall" />
       <keyword name="evaluateVar" id="evaluateVar" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.Security.Checks.djangoXssVulnerability.html#evaluateVar" />
       <keyword name="excepthook" id="excepthook" ref="eric7.eric7_ide.html#excepthook" />
@@ -19642,6 +19769,7 @@
       <keyword name="patchSubprocess" id="patchSubprocess" ref="eric7.DebugClients.Python.SubprocessExtension.html#patchSubprocess" />
       <keyword name="patch_circup" id="patch_circup" ref="eric7.MicroPython.Devices.CircuitPythonUpdater.CircupFunctions.html#patch_circup" />
       <keyword name="pbkdf2" id="pbkdf2" ref="eric7.Utilities.crypto.py3PBKDF2.html#pbkdf2" />
+      <keyword name="picowWiFiConnect (Module)" id="picowWiFiConnect (Module)" ref="eric7.MicroPython.Devices.MCUScripts.picowWiFiConnect.html" />
       <keyword name="pipdeptree (Module)" id="pipdeptree (Module)" ref="eric7.PipInterface.pipdeptree.html" />
       <keyword name="piplicenses (Module)" id="piplicenses (Module)" ref="eric7.PipInterface.piplicenses.html" />
       <keyword name="pixmapFileToDataUrl" id="pixmapFileToDataUrl" ref="eric7.WebBrowser.Tools.WebBrowserTools.html#pixmapFileToDataUrl" />
@@ -20014,6 +20142,7 @@
       <file>eric7.EricNetwork.EricFtp.html</file>
       <file>eric7.EricNetwork.EricGoogleMail.html</file>
       <file>eric7.EricNetwork.EricGoogleMailHelpers.html</file>
+      <file>eric7.EricNetwork.EricIPv4InputWidget.html</file>
       <file>eric7.EricNetwork.EricJsonClient.html</file>
       <file>eric7.EricNetwork.EricJsonServer.html</file>
       <file>eric7.EricNetwork.EricJsonStreamReader.html</file>
@@ -20148,6 +20277,8 @@
       <file>eric7.MicroPython.Devices.EspDialogs.EspBackupRestoreFirmwareDialog.html</file>
       <file>eric7.MicroPython.Devices.EspDialogs.EspFirmwareSelectionDialog.html</file>
       <file>eric7.MicroPython.Devices.GenericMicroPythonDevices.html</file>
+      <file>eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect.html</file>
+      <file>eric7.MicroPython.Devices.MCUScripts.picowWiFiConnect.html</file>
       <file>eric7.MicroPython.Devices.MicrobitDevices.html</file>
       <file>eric7.MicroPython.Devices.PyBoardDevices.html</file>
       <file>eric7.MicroPython.Devices.RP2040Devices.html</file>
@@ -20165,6 +20296,13 @@
       <file>eric7.MicroPython.ShowModulesDialog.html</file>
       <file>eric7.MicroPython.UF2FlashDialog.html</file>
       <file>eric7.MicroPython.UnknownDevicesDialog.html</file>
+      <file>eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html</file>
+      <file>eric7.MicroPython.WifiDialogs.WifiApStationsDialog.html</file>
+      <file>eric7.MicroPython.WifiDialogs.WifiConnectionDialog.html</file>
+      <file>eric7.MicroPython.WifiDialogs.WifiController.html</file>
+      <file>eric7.MicroPython.WifiDialogs.WifiCountryDialog.html</file>
+      <file>eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html</file>
+      <file>eric7.MicroPython.WifiDialogs.WifiStatusDialog.html</file>
       <file>eric7.MultiProject.AddProjectDialog.html</file>
       <file>eric7.MultiProject.MultiProject.html</file>
       <file>eric7.MultiProject.MultiProjectBrowser.html</file>
@@ -21142,7 +21280,9 @@
       <file>index-eric7.JediInterface.html</file>
       <file>index-eric7.MicroPython.Devices.CircuitPythonUpdater.html</file>
       <file>index-eric7.MicroPython.Devices.EspDialogs.html</file>
+      <file>index-eric7.MicroPython.Devices.MCUScripts.html</file>
       <file>index-eric7.MicroPython.Devices.html</file>
+      <file>index-eric7.MicroPython.WifiDialogs.html</file>
       <file>index-eric7.MicroPython.html</file>
       <file>index-eric7.MultiProject.html</file>
       <file>index-eric7.Network.IRC.html</file>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Documentation/Source/eric7.EricNetwork.EricIPv4InputWidget.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,241 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.EricNetwork.EricIPv4InputWidget</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.EricNetwork.EricIPv4InputWidget</h1>
+
+<p>
+Module implementing a widget to enter an IPv4 address.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricIPv4InputWidget">EricIPv4InputWidget</a></td>
+<td>Class implementing a widget to enter an IPv4 address.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="EricIPv4InputWidget" ID="EricIPv4InputWidget"></a>
+<h2>EricIPv4InputWidget</h2>
+
+<p>
+    Class implementing a widget to enter an IPv4 address.
+</p>
+<h3>Signals</h3>
+<dl>
+
+<dt>addressChanged()</dt>
+<dd>
+emitted to indicate a change of the entered IPv4 address
+</dd>
+</dl>
+<h3>Derived from</h3>
+QWidget, Ui_EricIPv4InputWidget
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricIPv4InputWidget.__init__">EricIPv4InputWidget</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#EricIPv4InputWidget.__clear">__clear</a></td>
+<td>Private slot to handle the clear button press.</td>
+</tr>
+<tr>
+<td><a href="#EricIPv4InputWidget.address">address</a></td>
+<td>Public method to get the IPv4 address as an ipaddress.IPv4Address object.</td>
+</tr>
+<tr>
+<td><a href="#EricIPv4InputWidget.clear">clear</a></td>
+<td>Public slot to clear the input fields.</td>
+</tr>
+<tr>
+<td><a href="#EricIPv4InputWidget.eventFilter">eventFilter</a></td>
+<td>Public method to filter pressing '.' to give focus to the next input field.</td>
+</tr>
+<tr>
+<td><a href="#EricIPv4InputWidget.hasAcceptableInput">hasAcceptableInput</a></td>
+<td>Public method to check, if the input is acceptable.</td>
+</tr>
+<tr>
+<td><a href="#EricIPv4InputWidget.setAddress">setAddress</a></td>
+<td>Public method to set the IPv4 address given an ipaddress.IPv4Address object.</td>
+</tr>
+<tr>
+<td><a href="#EricIPv4InputWidget.setText">setText</a></td>
+<td>Public method to set the IPv4 address given a string.</td>
+</tr>
+<tr>
+<td><a href="#EricIPv4InputWidget.text">text</a></td>
+<td>Public method to get the IPv4 address as a string.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="EricIPv4InputWidget.__init__" ID="EricIPv4InputWidget.__init__"></a>
+<h4>EricIPv4InputWidget (Constructor)</h4>
+<b>EricIPv4InputWidget</b>(<i>parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="EricIPv4InputWidget.__clear" ID="EricIPv4InputWidget.__clear"></a>
+<h4>EricIPv4InputWidget.__clear</h4>
+<b>__clear</b>(<i></i>)
+
+<p>
+        Private slot to handle the clear button press.
+</p>
+<a NAME="EricIPv4InputWidget.address" ID="EricIPv4InputWidget.address"></a>
+<h4>EricIPv4InputWidget.address</h4>
+<b>address</b>(<i></i>)
+
+<p>
+        Public method to get the IPv4 address as an ipaddress.IPv4Address object.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+IPv4 address
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+ipaddress.IPv4Address
+</dd>
+</dl>
+<a NAME="EricIPv4InputWidget.clear" ID="EricIPv4InputWidget.clear"></a>
+<h4>EricIPv4InputWidget.clear</h4>
+<b>clear</b>(<i></i>)
+
+<p>
+        Public slot to clear the input fields.
+</p>
+<a NAME="EricIPv4InputWidget.eventFilter" ID="EricIPv4InputWidget.eventFilter"></a>
+<h4>EricIPv4InputWidget.eventFilter</h4>
+<b>eventFilter</b>(<i>obj, evt</i>)
+
+<p>
+        Public method to filter pressing '.' to give focus to the next input field.
+</p>
+<dl>
+
+<dt><i>obj</i> (QObject)</dt>
+<dd>
+reference to the object
+</dd>
+<dt><i>evt</i> (QEvent)</dt>
+<dd>
+reference to the event object
+</dd>
+</dl>
+<a NAME="EricIPv4InputWidget.hasAcceptableInput" ID="EricIPv4InputWidget.hasAcceptableInput"></a>
+<h4>EricIPv4InputWidget.hasAcceptableInput</h4>
+<b>hasAcceptableInput</b>(<i></i>)
+
+<p>
+        Public method to check, if the input is acceptable.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating acceptable input
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="EricIPv4InputWidget.setAddress" ID="EricIPv4InputWidget.setAddress"></a>
+<h4>EricIPv4InputWidget.setAddress</h4>
+<b>setAddress</b>(<i>address</i>)
+
+<p>
+        Public method to set the IPv4 address given an ipaddress.IPv4Address object.
+</p>
+<dl>
+
+<dt><i>address</i> (ipaddress.IPv4Address)</dt>
+<dd>
+IPv4 address
+</dd>
+</dl>
+<a NAME="EricIPv4InputWidget.setText" ID="EricIPv4InputWidget.setText"></a>
+<h4>EricIPv4InputWidget.setText</h4>
+<b>setText</b>(<i>address</i>)
+
+<p>
+        Public method to set the IPv4 address given a string.
+</p>
+<dl>
+
+<dt><i>address</i> (str)</dt>
+<dd>
+IPv4 address
+</dd>
+</dl>
+<a NAME="EricIPv4InputWidget.text" ID="EricIPv4InputWidget.text"></a>
+<h4>EricIPv4InputWidget.text</h4>
+<b>text</b>(<i></i>)
+
+<p>
+        Public method to get the IPv4 address as a string.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+IPv4 address
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</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.Devices.DeviceBase.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.Devices.DeviceBase.html	Fri Mar 03 11:31:53 2023 +0100
@@ -47,19 +47,19 @@
     the time on the board and getting board related data. Supported file system
     commands are:
     <ul>
-    <li>ls: directory listing</li>
+    <li>cd: change directory</li>
+    <li>fileSystemInfo: get information about the file system
+    <li>get: get a file from the connected device</li>
+    <li>getData: read data of a file of the connected device</li>
     <li>lls: directory listing with meta data</li>
-    <li>cd: change directory</li>
-    <li>pwd: get the current directory</li>
+    <li>ls: directory listing</li>
+    <li>mkdir: create a new directory</li>
     <li>put: copy a file to the connected device</li>
     <li>putData: write data to a file of the connected device</li>
-    <li>get: get a file from the connected device</li>
-    <li>getData: read data of a file of the connected device</li>
+    <li>pwd: get the current directory</li>
     <li>rm: remove a file from the connected device</li>
+    <li>rmdir: remove an empty directory</li>
     <li>rmrf: remove a file/directory recursively (like 'rm -rf' in bash)
-    <li>mkdir: create a new directory</li>
-    <li>rmdir: remove an empty directory</li>
-    <li>fileSystemInfo: get information about the file system
     </ul>
 </p>
 <p>
@@ -70,8 +70,26 @@
         information</li>
     <li>getModules: get a list of built-in modules</li>
     <li>getTime: get the current time</li>
+    <li>showTime: show the current time of the connected device</li>
     <li>syncTime: synchronize the time of the connected device</li>
-    <li>showTime: show the current time of the connected device</li>
+    </ul>
+</p>
+<p>
+    Supported WiFi commands are:
+    <ul>
+    <li>hasWifi: check, if the board has WiFi functionality</li>
+    <li>getWifiData: get WiFi status data</li>
+    <li>connectWifi: connect to a WiFi network</li>
+    <li>disconnectWifi: disconnect from a WiFi network</li>
+    <li>writeCredentials: save the WiFi credentials to the board and create
+        functionality to auto-connect at boot time</li>
+    <li>removeCredentials: remove the saved credentials</li>
+    <li>checkInternet: check, if internet access is possible</li>
+    <li>scanNetworks: scan for available WiFi networks</li>
+    <li>deactivateInterface: deactivate a WiFi interface</li>
+    <li>startAccessPoint: start an access point</li>
+    <li>stopAccessPoint: stop the access point</li>
+    <li>getConnectedClients: get a list of connected WiFi clients</li>
     </ul>
 </p>
 <h3>Derived from</h3>
@@ -111,6 +129,10 @@
 <td>Public method to add device specific entries to the given menu.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.addDeviceWifiEntries">addDeviceWifiEntries</a></td>
+<td>Public method to add device specific entries to the given menu.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.canRunScript">canRunScript</a></td>
 <td>Public method to determine, if a script can be executed.</td>
 </tr>
@@ -135,10 +157,26 @@
 <td>Public method to check the validity of the device data determined during connecting the device.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.checkInternet">checkInternet</a></td>
+<td>Public method to check, if the internet can be reached.</td>
+</tr>
+<tr>
+<td><a href="#BaseDevice.connectWifi">connectWifi</a></td>
+<td>Public method to connect a device to a WiFi network.</td>
+</tr>
+<tr>
+<td><a href="#BaseDevice.deactivateInterface">deactivateInterface</a></td>
+<td>Public method to deactivate a given WiFi interface of the connected device.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.deviceName">deviceName</a></td>
 <td>Public method to get the name of the device.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.disconnectWifi">disconnectWifi</a></td>
+<td>Public method to disconnect a device from the WiFi network.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.downloadFirmware">downloadFirmware</a></td>
 <td>Public method to download the device firmware.</td>
 </tr>
@@ -159,6 +197,10 @@
 <td>Public method to get some information data of the connected board.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.getConnectedClients">getConnectedClients</a></td>
+<td>Public method to get a list of connected clients.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.getData">getData</a></td>
 <td>Public method to read data from the connected device.</td>
 </tr>
@@ -191,6 +233,10 @@
 <td>Public method to get the current time of the device.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.getWifiData">getWifiData</a></td>
+<td>Public method to get data related to the current WiFi status.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.getWorkspace">getWorkspace</a></td>
 <td>Public method to get the workspace directory.</td>
 </tr>
@@ -199,6 +245,10 @@
 <td>Public slot handling a data floof from the device.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.hasBluetooth">hasBluetooth</a></td>
+<td>Public method to check the availability of Bluetooth.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.hasCircuitPython">hasCircuitPython</a></td>
 <td>Public method to check, if the connected device is flashed with CircuitPython.</td>
 </tr>
@@ -207,6 +257,10 @@
 <td>Public method to check, if the device has a configured documentation URL.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.hasEthernet">hasEthernet</a></td>
+<td>Public method to check the availability of Ethernet.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.hasFirmwareUrl">hasFirmwareUrl</a></td>
 <td>Public method to check, if the device has a configured firmware download URL.</td>
 </tr>
@@ -219,6 +273,10 @@
 <td>Public method to check, if the device supports time commands.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.hasWifi">hasWifi</a></td>
+<td>Public method to check the availability of WiFi.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.lls">lls</a></td>
 <td>Public method to get a long directory listing of the connected device including meta data.</td>
 </tr>
@@ -243,6 +301,10 @@
 <td>Public method to get the current directory of the connected device.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.removeCredentials">removeCredentials</a></td>
+<td>Public method to remove the saved credentials from the connected device.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.rm">rm</a></td>
 <td>Public method to remove a file from the connected device.</td>
 </tr>
@@ -259,6 +321,10 @@
 <td>Public method to run the given Python script.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.scanNetworks">scanNetworks</a></td>
+<td>Public method to scan for available WiFi networks.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.selectDeviceDirectory">selectDeviceDirectory</a></td>
 <td>Public method to select the device directory from a list of detected ones.</td>
 </tr>
@@ -287,6 +353,14 @@
 <td>Public method to set the REPL status and dependent status.</td>
 </tr>
 <tr>
+<td><a href="#BaseDevice.startAccessPoint">startAccessPoint</a></td>
+<td>Public method to start the access point interface.</td>
+</tr>
+<tr>
+<td><a href="#BaseDevice.stopAccessPoint">stopAccessPoint</a></td>
+<td>Public method to stop the access point interface.</td>
+</tr>
+<tr>
 <td><a href="#BaseDevice.supportsLocalFileAccess">supportsLocalFileAccess</a></td>
 <td>Public method to indicate file access via a local directory.</td>
 </tr>
@@ -294,6 +368,10 @@
 <td><a href="#BaseDevice.syncTime">syncTime</a></td>
 <td>Public method to set the time of the connected device to the local computer's time.</td>
 </tr>
+<tr>
+<td><a href="#BaseDevice.writeCredentials">writeCredentials</a></td>
+<td>Public method to write the given credentials to the connected device and modify the start script to connect automatically.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -412,6 +490,20 @@
 reference to the context menu
 </dd>
 </dl>
+<a NAME="BaseDevice.addDeviceWifiEntries" ID="BaseDevice.addDeviceWifiEntries"></a>
+<h4>BaseDevice.addDeviceWifiEntries</h4>
+<b>addDeviceWifiEntries</b>(<i>menu</i>)
+
+<p>
+        Public method to add device specific entries to the given menu.
+</p>
+<dl>
+
+<dt><i>menu</i> (QMenu)</dt>
+<dd>
+reference to the context menu
+</dd>
+</dl>
 <a NAME="BaseDevice.canRunScript" ID="BaseDevice.canRunScript"></a>
 <h4>BaseDevice.canRunScript</h4>
 <b>canRunScript</b>(<i></i>)
@@ -541,6 +633,82 @@
 bool
 </dd>
 </dl>
+<a NAME="BaseDevice.checkInternet" ID="BaseDevice.checkInternet"></a>
+<h4>BaseDevice.checkInternet</h4>
+<b>checkInternet</b>(<i></i>)
+
+<p>
+        Public method to check, if the internet can be reached.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating reachability and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="BaseDevice.connectWifi" ID="BaseDevice.connectWifi"></a>
+<h4>BaseDevice.connectWifi</h4>
+<b>connectWifi</b>(<i>ssid, password</i>)
+
+<p>
+        Public method to connect a device to a WiFi network.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+name (SSID) of the WiFi network
+</dd>
+<dt><i>password</i> (str)</dt>
+<dd>
+password needed to connect
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the connection status and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="BaseDevice.deactivateInterface" ID="BaseDevice.deactivateInterface"></a>
+<h4>BaseDevice.deactivateInterface</h4>
+<b>deactivateInterface</b>(<i>interface</i>)
+
+<p>
+        Public method to deactivate a given WiFi interface of the connected device.
+</p>
+<dl>
+
+<dt><i>interface</i> (str)</dt>
+<dd>
+designation of the interface to be deactivated (one of 'AP'
+            or 'STA')
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containg a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="BaseDevice.deviceName" ID="BaseDevice.deviceName"></a>
 <h4>BaseDevice.deviceName</h4>
 <b>deviceName</b>(<i></i>)
@@ -560,6 +728,25 @@
 str
 </dd>
 </dl>
+<a NAME="BaseDevice.disconnectWifi" ID="BaseDevice.disconnectWifi"></a>
+<h4>BaseDevice.disconnectWifi</h4>
+<b>disconnectWifi</b>(<i></i>)
+
+<p>
+        Public method to disconnect a device from the WiFi network.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="BaseDevice.downloadFirmware" ID="BaseDevice.downloadFirmware"></a>
 <h4>BaseDevice.downloadFirmware</h4>
 <b>downloadFirmware</b>(<i></i>)
@@ -678,6 +865,26 @@
 raised to indicate an issue with the device
 </dd>
 </dl>
+<a NAME="BaseDevice.getConnectedClients" ID="BaseDevice.getConnectedClients"></a>
+<h4>BaseDevice.getConnectedClients</h4>
+<b>getConnectedClients</b>(<i></i>)
+
+<p>
+        Public method to get a list of connected clients.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+a tuple containing a list of tuples containing the client MAC-Address
+            and the RSSI (if supported and available) and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of ([(bytes, int)], str)
+</dd>
+</dl>
 <a NAME="BaseDevice.getData" ID="BaseDevice.getData"></a>
 <h4>BaseDevice.getData</h4>
 <b>getData</b>(<i>deviceFileName</i>)
@@ -713,12 +920,19 @@
 </dl>
 <a NAME="BaseDevice.getDeviceData" ID="BaseDevice.getDeviceData"></a>
 <h4>BaseDevice.getDeviceData</h4>
-<b>getDeviceData</b>(<i></i>)
+<b>getDeviceData</b>(<i>key=None</i>)
 
 <p>
         Public method to get a copy of the determined device data.
 </p>
 <dl>
+
+<dt><i>key</i> (str (optional))</dt>
+<dd>
+name of the data to get (None to get all data) (defaults to None)
+</dd>
+</dl>
+<dl>
 <dt>Return:</dt>
 <dd>
 dictionary containing the essential device data
@@ -859,6 +1073,26 @@
 raised to indicate an issue with the device
 </dd>
 </dl>
+<a NAME="BaseDevice.getWifiData" ID="BaseDevice.getWifiData"></a>
+<h4>BaseDevice.getWifiData</h4>
+<b>getWifiData</b>(<i></i>)
+
+<p>
+        Public method to get data related to the current WiFi status.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple of three dictionaries containing the WiFi status data
+            for the WiFi client, access point and overall data
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (dict, dict, dict)
+</dd>
+</dl>
 <a NAME="BaseDevice.getWorkspace" ID="BaseDevice.getWorkspace"></a>
 <h4>BaseDevice.getWorkspace</h4>
 <b>getWorkspace</b>(<i></i>)
@@ -885,6 +1119,25 @@
 <p>
         Public slot handling a data floof from the device.
 </p>
+<a NAME="BaseDevice.hasBluetooth" ID="BaseDevice.hasBluetooth"></a>
+<h4>BaseDevice.hasBluetooth</h4>
+<b>hasBluetooth</b>(<i></i>)
+
+<p>
+        Public method to check the availability of Bluetooth.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating the availability of Bluetooth
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
 <a NAME="BaseDevice.hasCircuitPython" ID="BaseDevice.hasCircuitPython"></a>
 <h4>BaseDevice.hasCircuitPython</h4>
 <b>hasCircuitPython</b>(<i></i>)
@@ -924,6 +1177,25 @@
 bool
 </dd>
 </dl>
+<a NAME="BaseDevice.hasEthernet" ID="BaseDevice.hasEthernet"></a>
+<h4>BaseDevice.hasEthernet</h4>
+<b>hasEthernet</b>(<i></i>)
+
+<p>
+        Public method to check the availability of Ethernet.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating the availability of Ethernet
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
 <a NAME="BaseDevice.hasFirmwareUrl" ID="BaseDevice.hasFirmwareUrl"></a>
 <h4>BaseDevice.hasFirmwareUrl</h4>
 <b>hasFirmwareUrl</b>(<i></i>)
@@ -985,6 +1257,26 @@
 bool
 </dd>
 </dl>
+<a NAME="BaseDevice.hasWifi" ID="BaseDevice.hasWifi"></a>
+<h4>BaseDevice.hasWifi</h4>
+<b>hasWifi</b>(<i></i>)
+
+<p>
+        Public method to check the availability of WiFi.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating the availability of WiFi
+            and the WiFi type (picow or pimoroni)
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="BaseDevice.lls" ID="BaseDevice.lls"></a>
 <h4>BaseDevice.lls</h4>
 <b>lls</b>(<i>dirname="", fullstat=False, showHidden=False</i>)
@@ -1184,6 +1476,25 @@
 raised to indicate an issue with the device
 </dd>
 </dl>
+<a NAME="BaseDevice.removeCredentials" ID="BaseDevice.removeCredentials"></a>
+<h4>BaseDevice.removeCredentials</h4>
+<b>removeCredentials</b>(<i></i>)
+
+<p>
+        Public method to remove the saved credentials from the connected device.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="BaseDevice.rm" ID="BaseDevice.rm"></a>
 <h4>BaseDevice.rm</h4>
 <b>rm</b>(<i>filename</i>)
@@ -1281,6 +1592,26 @@
 script to be executed
 </dd>
 </dl>
+<a NAME="BaseDevice.scanNetworks" ID="BaseDevice.scanNetworks"></a>
+<h4>BaseDevice.scanNetworks</h4>
+<b>scanNetworks</b>(<i></i>)
+
+<p>
+        Public method to scan for available WiFi networks.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the list of available networks as a tuple of 'Name',
+            'MAC-Address', 'channel', 'RSSI' and 'security' and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (list of tuple of (str, str, int, int, str), str)
+</dd>
+</dl>
 <a NAME="BaseDevice.selectDeviceDirectory" ID="BaseDevice.selectDeviceDirectory"></a>
 <h4>BaseDevice.selectDeviceDirectory</h4>
 <b>selectDeviceDirectory</b>(<i>deviceDirectories</i>)
@@ -1389,6 +1720,64 @@
 flag indicating the active status
 </dd>
 </dl>
+<a NAME="BaseDevice.startAccessPoint" ID="BaseDevice.startAccessPoint"></a>
+<h4>BaseDevice.startAccessPoint</h4>
+<b>startAccessPoint</b>(<i>ssid, security=None, password=None, ifconfig=None</i>)
+
+<p>
+        Public method to start the access point interface.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+SSID of the access point
+</dd>
+<dt><i>security</i> (int (optional))</dt>
+<dd>
+security method (defaults to None)
+</dd>
+<dt><i>password</i> (str (optional))</dt>
+<dd>
+password (defaults to None)
+</dd>
+<dt><i>ifconfig</i> (tuple of (str, str, str, str))</dt>
+<dd>
+IPv4 configuration for the access point if not default
+            (IPv4 address, netmask, gateway address, DNS server address)
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="BaseDevice.stopAccessPoint" ID="BaseDevice.stopAccessPoint"></a>
+<h4>BaseDevice.stopAccessPoint</h4>
+<b>stopAccessPoint</b>(<i></i>)
+
+<p>
+        Public method to stop the access point interface.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containg a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="BaseDevice.supportsLocalFileAccess" ID="BaseDevice.supportsLocalFileAccess"></a>
 <h4>BaseDevice.supportsLocalFileAccess</h4>
 <b>supportsLocalFileAccess</b>(<i></i>)
@@ -1435,6 +1824,37 @@
 raised to indicate an issue with the device
 </dd>
 </dl>
+<a NAME="BaseDevice.writeCredentials" ID="BaseDevice.writeCredentials"></a>
+<h4>BaseDevice.writeCredentials</h4>
+<b>writeCredentials</b>(<i>ssid, password</i>)
+
+<p>
+        Public method to write the given credentials to the connected device and modify
+        the start script to connect automatically.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+SSID of the network to connect to
+</dd>
+<dt><i>password</i> (str)</dt>
+<dd>
+password needed to authenticate
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</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.Devices.EspDevices.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.Devices.EspDevices.html	Fri Mar 03 11:31:53 2023 +0100
@@ -140,14 +140,34 @@
 <td>Public method to determine, if a REPL can be started.</td>
 </tr>
 <tr>
+<td><a href="#EspDevice.checkInternet">checkInternet</a></td>
+<td>Public method to check, if the internet can be reached.</td>
+</tr>
+<tr>
+<td><a href="#EspDevice.connectWifi">connectWifi</a></td>
+<td>Public method to connect a device to a WiFi network.</td>
+</tr>
+<tr>
+<td><a href="#EspDevice.deactivateInterface">deactivateInterface</a></td>
+<td>Public method to deactivate a given WiFi interface of the connected device.</td>
+</tr>
+<tr>
 <td><a href="#EspDevice.deviceName">deviceName</a></td>
 <td>Public method to get the name of the device.</td>
 </tr>
 <tr>
+<td><a href="#EspDevice.disconnectWifi">disconnectWifi</a></td>
+<td>Public method to disconnect a device from the WiFi network.</td>
+</tr>
+<tr>
 <td><a href="#EspDevice.forceInterrupt">forceInterrupt</a></td>
 <td>Public method to determine the need for an interrupt when opening the serial connection.</td>
 </tr>
 <tr>
+<td><a href="#EspDevice.getConnectedClients">getConnectedClients</a></td>
+<td>Public method to get a list of connected clients.</td>
+</tr>
+<tr>
 <td><a href="#EspDevice.getDocumentationUrl">getDocumentationUrl</a></td>
 <td>Public method to get the device documentation URL.</td>
 </tr>
@@ -156,17 +176,45 @@
 <td>Public method to get the device firmware download URL.</td>
 </tr>
 <tr>
+<td><a href="#EspDevice.getWifiData">getWifiData</a></td>
+<td>Public method to get data related to the current WiFi status.</td>
+</tr>
+<tr>
 <td><a href="#EspDevice.hasFlashMenuEntry">hasFlashMenuEntry</a></td>
 <td>Public method to check, if the device has its own flash menu entry.</td>
 </tr>
 <tr>
+<td><a href="#EspDevice.hasWifi">hasWifi</a></td>
+<td>Public method to check the availability of WiFi.</td>
+</tr>
+<tr>
+<td><a href="#EspDevice.removeCredentials">removeCredentials</a></td>
+<td>Public method to remove the saved credentials from the connected device.</td>
+</tr>
+<tr>
 <td><a href="#EspDevice.runScript">runScript</a></td>
 <td>Public method to run the given Python script.</td>
 </tr>
 <tr>
+<td><a href="#EspDevice.scanNetworks">scanNetworks</a></td>
+<td>Public method to scan for available WiFi networks.</td>
+</tr>
+<tr>
 <td><a href="#EspDevice.setButtons">setButtons</a></td>
 <td>Public method to enable the supported action buttons.</td>
 </tr>
+<tr>
+<td><a href="#EspDevice.startAccessPoint">startAccessPoint</a></td>
+<td>Public method to start the access point interface.</td>
+</tr>
+<tr>
+<td><a href="#EspDevice.stopAccessPoint">stopAccessPoint</a></td>
+<td>Public method to stop the access point interface.</td>
+</tr>
+<tr>
+<td><a href="#EspDevice.writeCredentials">writeCredentials</a></td>
+<td>Public method to write the given credentials to the connected device and modify the start script to connect automatically.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -412,6 +460,89 @@
 tuple of (bool, str)
 </dd>
 </dl>
+<a NAME="EspDevice.checkInternet" ID="EspDevice.checkInternet"></a>
+<h4>EspDevice.checkInternet</h4>
+<b>checkInternet</b>(<i></i>)
+
+<p>
+        Public method to check, if the internet can be reached.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating reachability and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="EspDevice.connectWifi" ID="EspDevice.connectWifi"></a>
+<h4>EspDevice.connectWifi</h4>
+<b>connectWifi</b>(<i>ssid, password</i>)
+
+<p>
+        Public method to connect a device to a WiFi network.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+name (SSID) of the WiFi network
+</dd>
+<dt><i>password</i> (str)</dt>
+<dd>
+password needed to connect
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the connection status and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="EspDevice.deactivateInterface" ID="EspDevice.deactivateInterface"></a>
+<h4>EspDevice.deactivateInterface</h4>
+<b>deactivateInterface</b>(<i>interface</i>)
+
+<p>
+        Public method to deactivate a given WiFi interface of the connected device.
+</p>
+<dl>
+
+<dt><i>interface</i> (str)</dt>
+<dd>
+designation of the interface to be deactivated (one of 'AP'
+            or 'STA')
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containg a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>ValueError</b>:</dt>
+<dd>
+raised to indicate a wrong value for the interface type
+</dd>
+</dl>
 <a NAME="EspDevice.deviceName" ID="EspDevice.deviceName"></a>
 <h4>EspDevice.deviceName</h4>
 <b>deviceName</b>(<i></i>)
@@ -431,6 +562,25 @@
 str
 </dd>
 </dl>
+<a NAME="EspDevice.disconnectWifi" ID="EspDevice.disconnectWifi"></a>
+<h4>EspDevice.disconnectWifi</h4>
+<b>disconnectWifi</b>(<i></i>)
+
+<p>
+        Public method to disconnect a device from the WiFi network.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="EspDevice.forceInterrupt" ID="EspDevice.forceInterrupt"></a>
 <h4>EspDevice.forceInterrupt</h4>
 <b>forceInterrupt</b>(<i></i>)
@@ -451,6 +601,26 @@
 bool
 </dd>
 </dl>
+<a NAME="EspDevice.getConnectedClients" ID="EspDevice.getConnectedClients"></a>
+<h4>EspDevice.getConnectedClients</h4>
+<b>getConnectedClients</b>(<i></i>)
+
+<p>
+        Public method to get a list of connected clients.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+a tuple containing a list of tuples containing the client MAC-Address
+            and the RSSI (if supported and available) and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of ([(bytes, int)], str)
+</dd>
+</dl>
 <a NAME="EspDevice.getDocumentationUrl" ID="EspDevice.getDocumentationUrl"></a>
 <h4>EspDevice.getDocumentationUrl</h4>
 <b>getDocumentationUrl</b>(<i></i>)
@@ -489,6 +659,33 @@
 str
 </dd>
 </dl>
+<a NAME="EspDevice.getWifiData" ID="EspDevice.getWifiData"></a>
+<h4>EspDevice.getWifiData</h4>
+<b>getWifiData</b>(<i></i>)
+
+<p>
+        Public method to get data related to the current WiFi status.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple of three dictionaries containing the WiFi status data
+            for the WiFi client, access point and overall data
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (dict, dict, dict)
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>OSError</b>:</dt>
+<dd>
+raised to indicate an issue with the device
+</dd>
+</dl>
 <a NAME="EspDevice.hasFlashMenuEntry" ID="EspDevice.hasFlashMenuEntry"></a>
 <h4>EspDevice.hasFlashMenuEntry</h4>
 <b>hasFlashMenuEntry</b>(<i></i>)
@@ -508,6 +705,45 @@
 bool
 </dd>
 </dl>
+<a NAME="EspDevice.hasWifi" ID="EspDevice.hasWifi"></a>
+<h4>EspDevice.hasWifi</h4>
+<b>hasWifi</b>(<i></i>)
+
+<p>
+        Public method to check the availability of WiFi.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating the availability of WiFi
+            and the WiFi type (esp32)
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="EspDevice.removeCredentials" ID="EspDevice.removeCredentials"></a>
+<h4>EspDevice.removeCredentials</h4>
+<b>removeCredentials</b>(<i></i>)
+
+<p>
+        Public method to remove the saved credentials from the connected device.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="EspDevice.runScript" ID="EspDevice.runScript"></a>
 <h4>EspDevice.runScript</h4>
 <b>runScript</b>(<i>script</i>)
@@ -522,6 +758,26 @@
 script to be executed
 </dd>
 </dl>
+<a NAME="EspDevice.scanNetworks" ID="EspDevice.scanNetworks"></a>
+<h4>EspDevice.scanNetworks</h4>
+<b>scanNetworks</b>(<i></i>)
+
+<p>
+        Public method to scan for available WiFi networks.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the list of available networks as a tuple of 'Name',
+            'MAC-Address', 'channel', 'RSSI' and 'security' and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (list of tuple of (str, str, int, int, str), str)
+</dd>
+</dl>
 <a NAME="EspDevice.setButtons" ID="EspDevice.setButtons"></a>
 <h4>EspDevice.setButtons</h4>
 <b>setButtons</b>(<i></i>)
@@ -529,6 +785,95 @@
 <p>
         Public method to enable the supported action buttons.
 </p>
+<a NAME="EspDevice.startAccessPoint" ID="EspDevice.startAccessPoint"></a>
+<h4>EspDevice.startAccessPoint</h4>
+<b>startAccessPoint</b>(<i>ssid, security=None, password=None, ifconfig=None</i>)
+
+<p>
+        Public method to start the access point interface.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+SSID of the access point
+</dd>
+<dt><i>security</i> (int (optional))</dt>
+<dd>
+security method (defaults to None)
+</dd>
+<dt><i>password</i> (str (optional))</dt>
+<dd>
+password (defaults to None)
+</dd>
+<dt><i>ifconfig</i> (tuple of (str, str, str, str))</dt>
+<dd>
+IPv4 configuration for the access point if not default
+            (IPv4 address, netmask, gateway address, DNS server address)
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="EspDevice.stopAccessPoint" ID="EspDevice.stopAccessPoint"></a>
+<h4>EspDevice.stopAccessPoint</h4>
+<b>stopAccessPoint</b>(<i></i>)
+
+<p>
+        Public method to stop the access point interface.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containg a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="EspDevice.writeCredentials" ID="EspDevice.writeCredentials"></a>
+<h4>EspDevice.writeCredentials</h4>
+<b>writeCredentials</b>(<i>ssid, password</i>)
+
+<p>
+        Public method to write the given credentials to the connected device and modify
+        the start script to connect automatically.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+SSID of the network to connect to
+</dd>
+<dt><i>password</i> (str)</dt>
+<dd>
+password needed to authenticate
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <div align="right"><a href="#top">Up</a></div>
 <hr />
 <hr />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect</h1>
+
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+
+<tr>
+<td><a href="#connectWiFi">connectWiFi</a></td>
+<td></td>
+</tr>
+</table>
+<hr />
+<hr />
+<a NAME="connectWiFi" ID="connectWiFi"></a>
+<h2>connectWiFi</h2>
+<b>connectWiFi</b>(<i></i>)
+
+<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.Devices.MCUScripts.picowWiFiConnect.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.Devices.MCUScripts.picowWiFiConnect</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.Devices.MCUScripts.picowWiFiConnect</h1>
+
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+
+<tr>
+<td><a href="#connectWiFi">connectWiFi</a></td>
+<td></td>
+</tr>
+</table>
+<hr />
+<hr />
+<a NAME="connectWiFi" ID="connectWiFi"></a>
+<h2>connectWiFi</h2>
+<b>connectWiFi</b>(<i></i>)
+
+<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.Devices.RP2040Devices.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.Devices.RP2040Devices.html	Fri Mar 03 11:31:53 2023 +0100
@@ -80,6 +80,10 @@
 <td>Private slot to flash a MicroPython firmware to the device.</td>
 </tr>
 <tr>
+<td><a href="#RP2040Device.__setCountry">__setCountry</a></td>
+<td>Private slot to configure the country of the connected RP2040 device.</td>
+</tr>
+<tr>
 <td><a href="#RP2040Device.__showFirmwareVersions">__showFirmwareVersions</a></td>
 <td>Private slot to show the firmware version of the connected device and the available firmware version.</td>
 </tr>
@@ -92,6 +96,10 @@
 <td>Public method to add device specific entries to the given menu.</td>
 </tr>
 <tr>
+<td><a href="#RP2040Device.addDeviceWifiEntries">addDeviceWifiEntries</a></td>
+<td>Public method to add device specific entries to the given menu.</td>
+</tr>
+<tr>
 <td><a href="#RP2040Device.canRunScript">canRunScript</a></td>
 <td>Public method to determine, if a script can be executed.</td>
 </tr>
@@ -108,14 +116,34 @@
 <td>Public method to determine, if a REPL can be started.</td>
 </tr>
 <tr>
+<td><a href="#RP2040Device.checkInternet">checkInternet</a></td>
+<td>Public method to check, if the internet can be reached.</td>
+</tr>
+<tr>
+<td><a href="#RP2040Device.connectWifi">connectWifi</a></td>
+<td>Public method to connect a device to a WiFi network.</td>
+</tr>
+<tr>
+<td><a href="#RP2040Device.deactivateInterface">deactivateInterface</a></td>
+<td>Public method to deactivate a given WiFi interface of the connected device.</td>
+</tr>
+<tr>
 <td><a href="#RP2040Device.deviceName">deviceName</a></td>
 <td>Public method to get the name of the device.</td>
 </tr>
 <tr>
+<td><a href="#RP2040Device.disconnectWifi">disconnectWifi</a></td>
+<td>Public method to disconnect a device from the WiFi network.</td>
+</tr>
+<tr>
 <td><a href="#RP2040Device.forceInterrupt">forceInterrupt</a></td>
 <td>Public method to determine the need for an interrupt when opening the serial connection.</td>
 </tr>
 <tr>
+<td><a href="#RP2040Device.getConnectedClients">getConnectedClients</a></td>
+<td>Public method to get a list of connected clients.</td>
+</tr>
+<tr>
 <td><a href="#RP2040Device.getDocumentationUrl">getDocumentationUrl</a></td>
 <td>Public method to get the device documentation URL.</td>
 </tr>
@@ -124,17 +152,45 @@
 <td>Public method to retrieve the entries for the downloads menu.</td>
 </tr>
 <tr>
+<td><a href="#RP2040Device.getWifiData">getWifiData</a></td>
+<td>Public method to get data related to the current WiFi status.</td>
+</tr>
+<tr>
 <td><a href="#RP2040Device.hasFlashMenuEntry">hasFlashMenuEntry</a></td>
 <td>Public method to check, if the device has its own flash menu entry.</td>
 </tr>
 <tr>
+<td><a href="#RP2040Device.hasWifi">hasWifi</a></td>
+<td>Public method to check the availability of WiFi.</td>
+</tr>
+<tr>
+<td><a href="#RP2040Device.removeCredentials">removeCredentials</a></td>
+<td>Public method to remove the saved credentials from the connected device.</td>
+</tr>
+<tr>
 <td><a href="#RP2040Device.runScript">runScript</a></td>
 <td>Public method to run the given Python script.</td>
 </tr>
 <tr>
+<td><a href="#RP2040Device.scanNetworks">scanNetworks</a></td>
+<td>Public method to scan for available WiFi networks.</td>
+</tr>
+<tr>
 <td><a href="#RP2040Device.setButtons">setButtons</a></td>
 <td>Public method to enable the supported action buttons.</td>
 </tr>
+<tr>
+<td><a href="#RP2040Device.startAccessPoint">startAccessPoint</a></td>
+<td>Public method to start the access point interface.</td>
+</tr>
+<tr>
+<td><a href="#RP2040Device.stopAccessPoint">stopAccessPoint</a></td>
+<td>Public method to stop the access point interface.</td>
+</tr>
+<tr>
+<td><a href="#RP2040Device.writeCredentials">writeCredentials</a></td>
+<td>Public method to write the given credentials to the connected device and modify the start script to connect automatically.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -199,6 +255,16 @@
 <p>
         Private slot to flash a MicroPython firmware to the device.
 </p>
+<a NAME="RP2040Device.__setCountry" ID="RP2040Device.__setCountry"></a>
+<h4>RP2040Device.__setCountry</h4>
+<b>__setCountry</b>(<i></i>)
+
+<p>
+        Private slot to configure the country of the connected RP2040 device.
+</p>
+<p>
+        The country is the two letter country code.
+</p>
 <a NAME="RP2040Device.__showFirmwareVersions" ID="RP2040Device.__showFirmwareVersions"></a>
 <h4>RP2040Device.__showFirmwareVersions</h4>
 <b>__showFirmwareVersions</b>(<i></i>)
@@ -244,6 +310,20 @@
 reference to the context menu
 </dd>
 </dl>
+<a NAME="RP2040Device.addDeviceWifiEntries" ID="RP2040Device.addDeviceWifiEntries"></a>
+<h4>RP2040Device.addDeviceWifiEntries</h4>
+<b>addDeviceWifiEntries</b>(<i>menu</i>)
+
+<p>
+        Public method to add device specific entries to the given menu.
+</p>
+<dl>
+
+<dt><i>menu</i> (QMenu)</dt>
+<dd>
+reference to the context menu
+</dd>
+</dl>
 <a NAME="RP2040Device.canRunScript" ID="RP2040Device.canRunScript"></a>
 <h4>RP2040Device.canRunScript</h4>
 <b>canRunScript</b>(<i></i>)
@@ -324,6 +404,89 @@
 tuple of (bool, str)
 </dd>
 </dl>
+<a NAME="RP2040Device.checkInternet" ID="RP2040Device.checkInternet"></a>
+<h4>RP2040Device.checkInternet</h4>
+<b>checkInternet</b>(<i></i>)
+
+<p>
+        Public method to check, if the internet can be reached.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating reachability and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="RP2040Device.connectWifi" ID="RP2040Device.connectWifi"></a>
+<h4>RP2040Device.connectWifi</h4>
+<b>connectWifi</b>(<i>ssid, password</i>)
+
+<p>
+        Public method to connect a device to a WiFi network.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+name (SSID) of the WiFi network
+</dd>
+<dt><i>password</i> (str)</dt>
+<dd>
+password needed to connect
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the connection status and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="RP2040Device.deactivateInterface" ID="RP2040Device.deactivateInterface"></a>
+<h4>RP2040Device.deactivateInterface</h4>
+<b>deactivateInterface</b>(<i>interface</i>)
+
+<p>
+        Public method to deactivate a given WiFi interface of the connected device.
+</p>
+<dl>
+
+<dt><i>interface</i> (str)</dt>
+<dd>
+designation of the interface to be deactivated (one of 'AP'
+            or 'STA')
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containg a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>ValueError</b>:</dt>
+<dd>
+raised to indicate a wrong value for the interface type
+</dd>
+</dl>
 <a NAME="RP2040Device.deviceName" ID="RP2040Device.deviceName"></a>
 <h4>RP2040Device.deviceName</h4>
 <b>deviceName</b>(<i></i>)
@@ -343,6 +506,25 @@
 str
 </dd>
 </dl>
+<a NAME="RP2040Device.disconnectWifi" ID="RP2040Device.disconnectWifi"></a>
+<h4>RP2040Device.disconnectWifi</h4>
+<b>disconnectWifi</b>(<i></i>)
+
+<p>
+        Public method to disconnect a device from the WiFi network.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="RP2040Device.forceInterrupt" ID="RP2040Device.forceInterrupt"></a>
 <h4>RP2040Device.forceInterrupt</h4>
 <b>forceInterrupt</b>(<i></i>)
@@ -363,6 +545,26 @@
 bool
 </dd>
 </dl>
+<a NAME="RP2040Device.getConnectedClients" ID="RP2040Device.getConnectedClients"></a>
+<h4>RP2040Device.getConnectedClients</h4>
+<b>getConnectedClients</b>(<i></i>)
+
+<p>
+        Public method to get a list of connected clients.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+a tuple containing a list of tuples containing the client MAC-Address
+            and the RSSI (if supported and available) and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of ([(bytes, int)], str)
+</dd>
+</dl>
 <a NAME="RP2040Device.getDocumentationUrl" ID="RP2040Device.getDocumentationUrl"></a>
 <h4>RP2040Device.getDocumentationUrl</h4>
 <b>getDocumentationUrl</b>(<i></i>)
@@ -402,6 +604,33 @@
 list of tuple of (str, str)
 </dd>
 </dl>
+<a NAME="RP2040Device.getWifiData" ID="RP2040Device.getWifiData"></a>
+<h4>RP2040Device.getWifiData</h4>
+<b>getWifiData</b>(<i></i>)
+
+<p>
+        Public method to get data related to the current WiFi status.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple of three dictionaries containing the WiFi status data
+            for the WiFi client, access point and overall data
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (dict, dict, dict)
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>OSError</b>:</dt>
+<dd>
+raised to indicate an issue with the device
+</dd>
+</dl>
 <a NAME="RP2040Device.hasFlashMenuEntry" ID="RP2040Device.hasFlashMenuEntry"></a>
 <h4>RP2040Device.hasFlashMenuEntry</h4>
 <b>hasFlashMenuEntry</b>(<i></i>)
@@ -421,6 +650,52 @@
 bool
 </dd>
 </dl>
+<a NAME="RP2040Device.hasWifi" ID="RP2040Device.hasWifi"></a>
+<h4>RP2040Device.hasWifi</h4>
+<b>hasWifi</b>(<i></i>)
+
+<p>
+        Public method to check the availability of WiFi.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating the availability of WiFi
+            and the WiFi type (picow or pimoroni)
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>OSError</b>:</dt>
+<dd>
+raised to indicate an issue with the device
+</dd>
+</dl>
+<a NAME="RP2040Device.removeCredentials" ID="RP2040Device.removeCredentials"></a>
+<h4>RP2040Device.removeCredentials</h4>
+<b>removeCredentials</b>(<i></i>)
+
+<p>
+        Public method to remove the saved credentials from the connected device.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="RP2040Device.runScript" ID="RP2040Device.runScript"></a>
 <h4>RP2040Device.runScript</h4>
 <b>runScript</b>(<i>script</i>)
@@ -435,6 +710,26 @@
 script to be executed
 </dd>
 </dl>
+<a NAME="RP2040Device.scanNetworks" ID="RP2040Device.scanNetworks"></a>
+<h4>RP2040Device.scanNetworks</h4>
+<b>scanNetworks</b>(<i></i>)
+
+<p>
+        Public method to scan for available WiFi networks.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the list of available networks as a tuple of 'Name',
+            'MAC-Address', 'channel', 'RSSI' and 'security' and an error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (list of tuple of (str, str, int, int, str), str)
+</dd>
+</dl>
 <a NAME="RP2040Device.setButtons" ID="RP2040Device.setButtons"></a>
 <h4>RP2040Device.setButtons</h4>
 <b>setButtons</b>(<i></i>)
@@ -442,6 +737,95 @@
 <p>
         Public method to enable the supported action buttons.
 </p>
+<a NAME="RP2040Device.startAccessPoint" ID="RP2040Device.startAccessPoint"></a>
+<h4>RP2040Device.startAccessPoint</h4>
+<b>startAccessPoint</b>(<i>ssid, security=None, password=None, ifconfig=None</i>)
+
+<p>
+        Public method to start the access point interface.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+SSID of the access point
+</dd>
+<dt><i>security</i> (int (optional))</dt>
+<dd>
+security method (defaults to None)
+</dd>
+<dt><i>password</i> (str (optional))</dt>
+<dd>
+password (defaults to None)
+</dd>
+<dt><i>ifconfig</i> (tuple of (str, str, str, str))</dt>
+<dd>
+IPv4 configuration for the access point if not default
+            (IPv4 address, netmask, gateway address, DNS server address)
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="RP2040Device.stopAccessPoint" ID="RP2040Device.stopAccessPoint"></a>
+<h4>RP2040Device.stopAccessPoint</h4>
+<b>stopAccessPoint</b>(<i></i>)
+
+<p>
+        Public method to stop the access point interface.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containg a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
+<a NAME="RP2040Device.writeCredentials" ID="RP2040Device.writeCredentials"></a>
+<h4>RP2040Device.writeCredentials</h4>
+<b>writeCredentials</b>(<i>ssid, password</i>)
+
+<p>
+        Public method to write the given credentials to the connected device and modify
+        the start script to connect automatically.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+SSID of the network to connect to
+</dd>
+<dt><i>password</i> (str)</dt>
+<dd>
+password needed to authenticate
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an error message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <div align="right"><a href="#top">Up</a></div>
 <hr />
 <hr />
--- a/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonDeviceInterface.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonDeviceInterface.html	Fri Mar 03 11:31:53 2023 +0100
@@ -57,7 +57,7 @@
 <h3>Class Attributes</h3>
 
 <table>
-<tr><td>None</td></tr>
+<tr><td>PasteModePrompt</td></tr><tr><td>TracebackMarker</td></tr>
 </table>
 <h3>Class Methods</h3>
 
@@ -73,6 +73,22 @@
 <td>Constructor</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>
@@ -101,6 +117,10 @@
 <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="#MicroPythonDeviceInterface.executeAsyncPaste">executeAsyncPaste</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="#MicroPythonDeviceInterface.handlePreferencesChanged">handlePreferencesChanged</a></td>
 <td>Public slot to handle a change of the preferences.</td>
 </tr>
@@ -137,6 +157,105 @@
 reference to the parent object
 </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>)
+
+<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.
+</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>
+<dd>
+bool
+</dd>
+</dl>
 <a NAME="MicroPythonDeviceInterface.__rawOff" ID="MicroPythonDeviceInterface.__rawOff"></a>
 <h4>MicroPythonDeviceInterface.__rawOff</h4>
 <b>__rawOff</b>(<i></i>)
@@ -158,7 +277,12 @@
 <dt>Return:</dt>
 <dd>
 flag indicating success
-@rtype bool
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="MicroPythonDeviceInterface.__readSerial" ID="MicroPythonDeviceInterface.__readSerial"></a>
@@ -204,7 +328,7 @@
 </p>
 <a NAME="MicroPythonDeviceInterface.execute" ID="MicroPythonDeviceInterface.execute"></a>
 <h4>MicroPythonDeviceInterface.execute</h4>
-<b>execute</b>(<i>commands</i>)
+<b>execute</b>(<i>commands, *, mode="raw", timeout=0</i>)
 
 <p>
         Public method to send commands to the connected device and return the
@@ -219,6 +343,16 @@
 <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>
@@ -232,6 +366,13 @@
 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="MicroPythonDeviceInterface.executeAsync" ID="MicroPythonDeviceInterface.executeAsync"></a>
 <h4>MicroPythonDeviceInterface.executeAsync</h4>
 <b>executeAsync</b>(<i>commandsList</i>)
@@ -247,6 +388,21 @@
 list of commands to be execute on the device
 </dd>
 </dl>
+<a NAME="MicroPythonDeviceInterface.executeAsyncPaste" ID="MicroPythonDeviceInterface.executeAsyncPaste"></a>
+<h4>MicroPythonDeviceInterface.executeAsyncPaste</h4>
+<b>executeAsyncPaste</b>(<i>commandsList</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 bytes)</dt>
+<dd>
+list of commands to be execute on the device
+</dd>
+</dl>
 <a NAME="MicroPythonDeviceInterface.handlePreferencesChanged" ID="MicroPythonDeviceInterface.handlePreferencesChanged"></a>
 <h4>MicroPythonDeviceInterface.handlePreferencesChanged</h4>
 <b>handlePreferencesChanged</b>(<i></i>)
--- a/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonSerialPort.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonSerialPort.html	Fri Mar 03 11:31:53 2023 +0100
@@ -177,7 +177,7 @@
 </dl>
 <a NAME="MicroPythonSerialPort.readUntil" ID="MicroPythonSerialPort.readUntil"></a>
 <h4>MicroPythonSerialPort.readUntil</h4>
-<b>readUntil</b>(<i>expected=b"\n", size=None</i>)
+<b>readUntil</b>(<i>expected=b"\n", size=None, timeout=0</i>)
 
 <p>
         Public method to read data until an expected sequence is found
@@ -189,9 +189,14 @@
 <dd>
 expected bytes sequence
 </dd>
-<dt><i>size</i> (int)</dt>
+<dt><i>size</i> (int (optional))</dt>
 <dd>
-maximum data to be read
+maximum data to be read (defaults to None)
+</dd>
+<dt><i>timeout</i> (int (optional))</dt>
+<dd>
+timeout in milliseconds (0 for configured default)
+            (defaults to 0)
 </dd>
 </dl>
 <dl>
--- a/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonWidget.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.MicroPythonWidget.html	Fri Mar 03 11:31:53 2023 +0100
@@ -188,10 +188,6 @@
 <td>Private slot to open the documentation URL for the selected device.</td>
 </tr>
 <tr>
-<td><a href="#MicroPythonWidget.__showError">__showError</a></td>
-<td>Private method to show some error message.</td>
-</tr>
-<tr>
 <td><a href="#MicroPythonWidget.__showImplementation">__showImplementation</a></td>
 <td>Private slot to show some implementation related information.</td>
 </tr>
@@ -232,6 +228,10 @@
 <td>Public method to determine the port path of the selected device.</td>
 </tr>
 <tr>
+<td><a href="#MicroPythonWidget.getDevice">getDevice</a></td>
+<td>Public method to get a reference to the current device.</td>
+</tr>
+<tr>
 <td><a href="#MicroPythonWidget.getDeviceWorkspace">getDeviceWorkspace</a></td>
 <td>Public method to get the workspace directory of the device.</td>
 </tr>
@@ -690,24 +690,6 @@
 <p>
         Private slot to open the documentation URL for the selected device.
 </p>
-<a NAME="MicroPythonWidget.__showError" ID="MicroPythonWidget.__showError"></a>
-<h4>MicroPythonWidget.__showError</h4>
-<b>__showError</b>(<i>method, error</i>)
-
-<p>
-        Private method to show some error message.
-</p>
-<dl>
-
-<dt><i>method</i> (str)</dt>
-<dd>
-name of the method the error occured in
-</dd>
-<dt><i>error</i> (str)</dt>
-<dd>
-error message
-</dd>
-</dl>
 <a NAME="MicroPythonWidget.__showImplementation" ID="MicroPythonWidget.__showImplementation"></a>
 <h4>MicroPythonWidget.__showImplementation</h4>
 <b>__showImplementation</b>(<i></i>)
@@ -858,6 +840,25 @@
 str
 </dd>
 </dl>
+<a NAME="MicroPythonWidget.getDevice" ID="MicroPythonWidget.getDevice"></a>
+<h4>MicroPythonWidget.getDevice</h4>
+<b>getDevice</b>(<i></i>)
+
+<p>
+        Public method to get a reference to the current device.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+reference to the current device
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+BaseDevice
+</dd>
+</dl>
 <a NAME="MicroPythonWidget.getDeviceWorkspace" ID="MicroPythonWidget.getDeviceWorkspace"></a>
 <h4>MicroPythonWidget.getDeviceWorkspace</h4>
 <b>getDeviceWorkspace</b>(<i></i>)
@@ -1045,6 +1046,24 @@
             are 'run', 'repl', 'files', 'chart', 'open', 'save'
 </dd>
 </dl>
+<a NAME="MicroPythonWidget.showError" ID="MicroPythonWidget.showError"></a>
+<h4>MicroPythonWidget.showError</h4>
+<b>showError</b>(<i>method, error</i>)
+
+<p>
+        Public method to show some error message.
+</p>
+<dl>
+
+<dt><i>method</i> (str)</dt>
+<dd>
+name of the method the error occured in
+</dd>
+<dt><i>error</i> (str)</dt>
+<dd>
+error message
+</dd>
+</dl>
 <a NAME="MicroPythonWidget.shutdown" ID="MicroPythonWidget.shutdown"></a>
 <h4>MicroPythonWidget.shutdown</h4>
 <b>shutdown</b>(<i></i>)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Documentation/Source/eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.WifiDialogs.WifiApConfigDialog</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.WifiDialogs.WifiApConfigDialog</h1>
+
+<p>
+Module implementing a dialog to configure the Access Point interface.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiApConfigDialog">WifiApConfigDialog</a></td>
+<td>Class implementing a dialog to configure the Access Point interface.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="WifiApConfigDialog" ID="WifiApConfigDialog"></a>
+<h2>WifiApConfigDialog</h2>
+
+<p>
+    Class implementing a dialog to configure the Access Point interface.
+</p>
+<h3>Derived from</h3>
+QDialog, Ui_WifiApConfigDialog
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiApConfigDialog.__init__">WifiApConfigDialog</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#WifiApConfigDialog.__updateOk">__updateOk</a></td>
+<td>Private method to update the enabled state of the OK button.</td>
+</tr>
+<tr>
+<td><a href="#WifiApConfigDialog.getApConfig">getApConfig</a></td>
+<td>Public method to get the entered access point configuration data.</td>
+</tr>
+<tr>
+<td><a href="#WifiApConfigDialog.on_apShowPasswordButton_clicked">on_apShowPasswordButton_clicked</a></td>
+<td>Private slot to show or hide the WiFi Access Point password.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="WifiApConfigDialog.__init__" ID="WifiApConfigDialog.__init__"></a>
+<h4>WifiApConfigDialog (Constructor)</h4>
+<b>WifiApConfigDialog</b>(<i>withIP, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>withIP</i> (bool)</dt>
+<dd>
+flag indicating to ask the user for an IP configuration
+</dd>
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="WifiApConfigDialog.__updateOk" ID="WifiApConfigDialog.__updateOk"></a>
+<h4>WifiApConfigDialog.__updateOk</h4>
+<b>__updateOk</b>(<i></i>)
+
+<p>
+        Private method to update the enabled state of the OK button.
+</p>
+<a NAME="WifiApConfigDialog.getApConfig" ID="WifiApConfigDialog.getApConfig"></a>
+<h4>WifiApConfigDialog.getApConfig</h4>
+<b>getApConfig</b>(<i></i>)
+
+<p>
+        Public method to get the entered access point configuration data.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the SSID, the password, the selected security mode
+            and a flag indicating to save the parameters to the settings
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (str, str, int, bool)
+</dd>
+</dl>
+<a NAME="WifiApConfigDialog.on_apShowPasswordButton_clicked" ID="WifiApConfigDialog.on_apShowPasswordButton_clicked"></a>
+<h4>WifiApConfigDialog.on_apShowPasswordButton_clicked</h4>
+<b>on_apShowPasswordButton_clicked</b>(<i>checked</i>)
+
+<p>
+        Private slot to show or hide the WiFi Access Point password.
+</p>
+<dl>
+
+<dt><i>checked</i> (bool)</dt>
+<dd>
+state of the button
+</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.WifiDialogs.WifiApStationsDialog.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.WifiDialogs.WifiApStationsDialog</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.WifiDialogs.WifiApStationsDialog</h1>
+
+<p>
+Module implementing a dialog showing the currently connected stations (clients).
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiApStationsDialog">WifiApStationsDialog</a></td>
+<td>Class documentation goes here.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="WifiApStationsDialog" ID="WifiApStationsDialog"></a>
+<h2>WifiApStationsDialog</h2>
+
+<p>
+    Class documentation goes here.
+</p>
+<h3>Derived from</h3>
+QDialog, Ui_WifiApStationsDialog
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiApStationsDialog.__init__">WifiApStationsDialog</a></td>
+<td>Constructor</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="WifiApStationsDialog.__init__" ID="WifiApStationsDialog.__init__"></a>
+<h4>WifiApStationsDialog (Constructor)</h4>
+<b>WifiApStationsDialog</b>(<i>stations, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>stations</i></dt>
+<dd>
+list of connected stations. Each entry is a tuple containing the
+            station's MAC-Address and the RSSI (if supported and available)
+</dd>
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</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.WifiDialogs.WifiConnectionDialog.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.WifiDialogs.WifiConnectionDialog</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.WifiDialogs.WifiConnectionDialog</h1>
+
+<p>
+Module implementing a dialog to enter the parameters needed to connect to a WiFi
+network.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiConnectionDialog">WifiConnectionDialog</a></td>
+<td>Class implementing a dialog to enter the parameters needed to connect to a WiFi network.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="WifiConnectionDialog" ID="WifiConnectionDialog"></a>
+<h2>WifiConnectionDialog</h2>
+
+<p>
+    Class implementing a dialog to enter the parameters needed to connect to a WiFi
+    network.
+</p>
+<h3>Derived from</h3>
+QDialog, Ui_WifiConnectionDialog
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiConnectionDialog.__init__">WifiConnectionDialog</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#WifiConnectionDialog.getConnectionParameters">getConnectionParameters</a></td>
+<td>Public method to get the entered connection parameters.</td>
+</tr>
+<tr>
+<td><a href="#WifiConnectionDialog.on_showPasswordButton_clicked">on_showPasswordButton_clicked</a></td>
+<td>Private slot to show or hide the password.</td>
+</tr>
+<tr>
+<td><a href="#WifiConnectionDialog.on_ssidEdit_textChanged">on_ssidEdit_textChanged</a></td>
+<td>Private slot handling a change of the SSID.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="WifiConnectionDialog.__init__" ID="WifiConnectionDialog.__init__"></a>
+<h4>WifiConnectionDialog (Constructor)</h4>
+<b>WifiConnectionDialog</b>(<i>parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="WifiConnectionDialog.getConnectionParameters" ID="WifiConnectionDialog.getConnectionParameters"></a>
+<h4>WifiConnectionDialog.getConnectionParameters</h4>
+<b>getConnectionParameters</b>(<i></i>)
+
+<p>
+        Public method to get the entered connection parameters.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the SSID, password and a flag indicating, if the
+            parameters shall be saved to the preferences
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (str, str, bool)
+</dd>
+</dl>
+<a NAME="WifiConnectionDialog.on_showPasswordButton_clicked" ID="WifiConnectionDialog.on_showPasswordButton_clicked"></a>
+<h4>WifiConnectionDialog.on_showPasswordButton_clicked</h4>
+<b>on_showPasswordButton_clicked</b>(<i>checked</i>)
+
+<p>
+        Private slot to show or hide the password.
+</p>
+<dl>
+
+<dt><i>checked</i> (bool)</dt>
+<dd>
+state of the button
+</dd>
+</dl>
+<a NAME="WifiConnectionDialog.on_ssidEdit_textChanged" ID="WifiConnectionDialog.on_ssidEdit_textChanged"></a>
+<h4>WifiConnectionDialog.on_ssidEdit_textChanged</h4>
+<b>on_ssidEdit_textChanged</b>(<i>ssid</i>)
+
+<p>
+        Private slot handling a change of the SSID.
+</p>
+<dl>
+
+<dt><i>ssid</i> (str)</dt>
+<dd>
+entered SSID
+</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.WifiDialogs.WifiController.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,274 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.WifiDialogs.WifiController</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.WifiDialogs.WifiController</h1>
+
+<p>
+Module implementing the WiFi related functionality.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiController">WifiController</a></td>
+<td>Class implementing the WiFi related functionality.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="WifiController" ID="WifiController"></a>
+<h2>WifiController</h2>
+
+<p>
+    Class implementing the WiFi related functionality.
+</p>
+<h3>Derived from</h3>
+QObject
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiController.__init__">WifiController</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__checkInternet">__checkInternet</a></td>
+<td>Private slot to check the availability of an internet connection.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__connectWifi">__connectWifi</a></td>
+<td>Private slot to connect the current device to a WiFi network.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__deactivateInterface">__deactivateInterface</a></td>
+<td>Private method to deactivate a given WiFi interface of the connected device.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__disconnectWifi">__disconnectWifi</a></td>
+<td>Private slot to disconnect the current device from the WiFi network.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__removeCredentials">__removeCredentials</a></td>
+<td>Private slot to remove the saved WiFi credentials from the connected device.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__scanNetwork">__scanNetwork</a></td>
+<td>Private slot to scan for visible WiFi networks.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__showConnectedClients">__showConnectedClients</a></td>
+<td>Private slot to show a list of WiFi clients connected to the Access Point interface.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__showWifiStatus">__showWifiStatus</a></td>
+<td>Private slot to show a dialog with the WiFi status of the current device.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__startAccessPoint">__startAccessPoint</a></td>
+<td>Private slot to start the Access Point interface of the connected device.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__startAccessPointIP">__startAccessPointIP</a></td>
+<td>Private slot to start the Access Point interface of the connected device with given IP parameters.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__stopAccessPoint">__stopAccessPoint</a></td>
+<td>Private slot to stop the Access Point interface of the connected device.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.__writeCredentials">__writeCredentials</a></td>
+<td>Private slot to save the WiFi login credentials to the connected device.</td>
+</tr>
+<tr>
+<td><a href="#WifiController.createMenu">createMenu</a></td>
+<td>Public method to create the WiFi submenu.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="WifiController.__init__" ID="WifiController.__init__"></a>
+<h4>WifiController (Constructor)</h4>
+<b>WifiController</b>(<i>microPython, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>microPython</i> (MicroPythonWidgep)</dt>
+<dd>
+reference to the MicroPython widget
+</dd>
+<dt><i>parent</i> (QObject (optional))</dt>
+<dd>
+reference to the parent object (defaults to None)
+</dd>
+</dl>
+<a NAME="WifiController.__checkInternet" ID="WifiController.__checkInternet"></a>
+<h4>WifiController.__checkInternet</h4>
+<b>__checkInternet</b>(<i></i>)
+
+<p>
+        Private slot to check the availability of an internet connection.
+</p>
+<a NAME="WifiController.__connectWifi" ID="WifiController.__connectWifi"></a>
+<h4>WifiController.__connectWifi</h4>
+<b>__connectWifi</b>(<i></i>)
+
+<p>
+        Private slot to connect the current device to a WiFi network.
+</p>
+<a NAME="WifiController.__deactivateInterface" ID="WifiController.__deactivateInterface"></a>
+<h4>WifiController.__deactivateInterface</h4>
+<b>__deactivateInterface</b>(<i>interface</i>)
+
+<p>
+        Private method to deactivate a given WiFi interface of the connected device.
+</p>
+<dl>
+
+<dt><i>interface</i> (str)</dt>
+<dd>
+designation of the interface to be deactivated (one of 'AP'
+            or 'STA')
+</dd>
+</dl>
+<a NAME="WifiController.__disconnectWifi" ID="WifiController.__disconnectWifi"></a>
+<h4>WifiController.__disconnectWifi</h4>
+<b>__disconnectWifi</b>(<i></i>)
+
+<p>
+        Private slot to disconnect the current device from the WiFi network.
+</p>
+<a NAME="WifiController.__removeCredentials" ID="WifiController.__removeCredentials"></a>
+<h4>WifiController.__removeCredentials</h4>
+<b>__removeCredentials</b>(<i></i>)
+
+<p>
+        Private slot to remove the saved WiFi credentials from the connected device.
+</p>
+<p>
+        This will not remove the auto-connect part of the boot script. This needs to be
+        done manually if desired.
+</p>
+<a NAME="WifiController.__scanNetwork" ID="WifiController.__scanNetwork"></a>
+<h4>WifiController.__scanNetwork</h4>
+<b>__scanNetwork</b>(<i></i>)
+
+<p>
+        Private slot to scan for visible WiFi networks.
+</p>
+<a NAME="WifiController.__showConnectedClients" ID="WifiController.__showConnectedClients"></a>
+<h4>WifiController.__showConnectedClients</h4>
+<b>__showConnectedClients</b>(<i></i>)
+
+<p>
+        Private slot to show a list of WiFi clients connected to the Access Point
+        interface.
+</p>
+<a NAME="WifiController.__showWifiStatus" ID="WifiController.__showWifiStatus"></a>
+<h4>WifiController.__showWifiStatus</h4>
+<b>__showWifiStatus</b>(<i></i>)
+
+<p>
+        Private slot to show a dialog with the WiFi status of the current device.
+</p>
+<a NAME="WifiController.__startAccessPoint" ID="WifiController.__startAccessPoint"></a>
+<h4>WifiController.__startAccessPoint</h4>
+<b>__startAccessPoint</b>(<i>withIP=False</i>)
+
+<p>
+        Private slot to start the Access Point interface of the connected device.
+</p>
+<dl>
+
+<dt><i>withIP</i> (bool)</dt>
+<dd>
+flag indicating to start the access point with an IP configuration
+</dd>
+</dl>
+<a NAME="WifiController.__startAccessPointIP" ID="WifiController.__startAccessPointIP"></a>
+<h4>WifiController.__startAccessPointIP</h4>
+<b>__startAccessPointIP</b>(<i></i>)
+
+<p>
+        Private slot to start the Access Point interface of the connected device
+        with given IP parameters.
+</p>
+<a NAME="WifiController.__stopAccessPoint" ID="WifiController.__stopAccessPoint"></a>
+<h4>WifiController.__stopAccessPoint</h4>
+<b>__stopAccessPoint</b>(<i></i>)
+
+<p>
+        Private slot to stop the Access Point interface of the connected device.
+</p>
+<a NAME="WifiController.__writeCredentials" ID="WifiController.__writeCredentials"></a>
+<h4>WifiController.__writeCredentials</h4>
+<b>__writeCredentials</b>(<i></i>)
+
+<p>
+        Private slot to save the WiFi login credentials to the connected device.
+</p>
+<p>
+        This will also modify the boot script to perform an automatic WiFi connection.
+</p>
+<a NAME="WifiController.createMenu" ID="WifiController.createMenu"></a>
+<h4>WifiController.createMenu</h4>
+<b>createMenu</b>(<i>menu</i>)
+
+<p>
+        Public method to create the WiFi submenu.
+</p>
+<dl>
+
+<dt><i>menu</i> (QMenu)</dt>
+<dd>
+reference to the parent menu
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+reference to the created menu
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QMenu
+</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.WifiDialogs.WifiCountryDialog.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.WifiDialogs.WifiCountryDialog</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.WifiDialogs.WifiCountryDialog</h1>
+
+<p>
+Module implementing a dialog to enter the country code for the WiFi interface.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiCountryDialog">WifiCountryDialog</a></td>
+<td>Class implementing a dialog to enter the country code for the WiFi interface.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="WifiCountryDialog" ID="WifiCountryDialog"></a>
+<h2>WifiCountryDialog</h2>
+
+<p>
+    Class implementing a dialog to enter the country code for the WiFi interface.
+</p>
+<h3>Derived from</h3>
+QDialog, Ui_WifiCountryDialog
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiCountryDialog.__init__">WifiCountryDialog</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#WifiCountryDialog.getCountry">getCountry</a></td>
+<td>Public method to get the entered country code.</td>
+</tr>
+<tr>
+<td><a href="#WifiCountryDialog.on_countryEdit_textChanged">on_countryEdit_textChanged</a></td>
+<td>Private slot handling a change of the country.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="WifiCountryDialog.__init__" ID="WifiCountryDialog.__init__"></a>
+<h4>WifiCountryDialog (Constructor)</h4>
+<b>WifiCountryDialog</b>(<i>parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="WifiCountryDialog.getCountry" ID="WifiCountryDialog.getCountry"></a>
+<h4>WifiCountryDialog.getCountry</h4>
+<b>getCountry</b>(<i></i>)
+
+<p>
+        Public method to get the entered country code.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the country code and a flag indicating to save it to
+            the settings
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (str, bool)
+</dd>
+</dl>
+<a NAME="WifiCountryDialog.on_countryEdit_textChanged" ID="WifiCountryDialog.on_countryEdit_textChanged"></a>
+<h4>WifiCountryDialog.on_countryEdit_textChanged</h4>
+<b>on_countryEdit_textChanged</b>(<i>country</i>)
+
+<p>
+        Private slot handling a change of the country.
+</p>
+<dl>
+
+<dt><i>country</i> (str)</dt>
+<dd>
+entered country code
+</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.WifiDialogs.WifiNetworksWindow.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.WifiDialogs.WifiNetworksWindow</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.WifiDialogs.WifiNetworksWindow</h1>
+
+<p>
+Module implementing a dialog showing the available WiFi networks.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiNetworksWindow">WifiNetworksWindow</a></td>
+<td>Class implementing a dialog showing the available WiFi networks.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="WifiNetworksWindow" ID="WifiNetworksWindow"></a>
+<h2>WifiNetworksWindow</h2>
+
+<p>
+    Class implementing a dialog showing the available WiFi networks.
+</p>
+<h3>Derived from</h3>
+QWidget, Ui_WifiNetworksWindow
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiNetworksWindow.__init__">WifiNetworksWindow</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#WifiNetworksWindow.__resizeColumns">__resizeColumns</a></td>
+<td>Private method to resize the columns of the result list.</td>
+</tr>
+<tr>
+<td><a href="#WifiNetworksWindow.__resort">__resort</a></td>
+<td>Private method to resort the networks list.</td>
+</tr>
+<tr>
+<td><a href="#WifiNetworksWindow.closeEvent">closeEvent</a></td>
+<td>Protected method to handle a window close event.</td>
+</tr>
+<tr>
+<td><a href="#WifiNetworksWindow.on_intervalSpinBox_valueChanged">on_intervalSpinBox_valueChanged</a></td>
+<td>Private slot handling a change of the periodic scan interval.</td>
+</tr>
+<tr>
+<td><a href="#WifiNetworksWindow.on_periodicCheckBox_toggled">on_periodicCheckBox_toggled</a></td>
+<td>Private slot handling the selection of a periodic scan.</td>
+</tr>
+<tr>
+<td><a href="#WifiNetworksWindow.scanNetworks">scanNetworks</a></td>
+<td>Public method to ask the device for a network scan and display the result.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="WifiNetworksWindow.__init__" ID="WifiNetworksWindow.__init__"></a>
+<h4>WifiNetworksWindow (Constructor)</h4>
+<b>WifiNetworksWindow</b>(<i>device, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>device</i> (BaseDevice)</dt>
+<dd>
+reference to the connected device
+</dd>
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="WifiNetworksWindow.__resizeColumns" ID="WifiNetworksWindow.__resizeColumns"></a>
+<h4>WifiNetworksWindow.__resizeColumns</h4>
+<b>__resizeColumns</b>(<i></i>)
+
+<p>
+        Private method to resize the columns of the result list.
+</p>
+<a NAME="WifiNetworksWindow.__resort" ID="WifiNetworksWindow.__resort"></a>
+<h4>WifiNetworksWindow.__resort</h4>
+<b>__resort</b>(<i></i>)
+
+<p>
+        Private method to resort the networks list.
+</p>
+<a NAME="WifiNetworksWindow.closeEvent" ID="WifiNetworksWindow.closeEvent"></a>
+<h4>WifiNetworksWindow.closeEvent</h4>
+<b>closeEvent</b>(<i>evt</i>)
+
+<p>
+        Protected method to handle a window close event.
+</p>
+<dl>
+
+<dt><i>evt</i> (QCloseEvent)</dt>
+<dd>
+reference to the close event
+</dd>
+</dl>
+<a NAME="WifiNetworksWindow.on_intervalSpinBox_valueChanged" ID="WifiNetworksWindow.on_intervalSpinBox_valueChanged"></a>
+<h4>WifiNetworksWindow.on_intervalSpinBox_valueChanged</h4>
+<b>on_intervalSpinBox_valueChanged</b>(<i>interval</i>)
+
+<p>
+        Private slot handling a change of the periodic scan interval.
+</p>
+<dl>
+
+<dt><i>interval</i> (int)</dt>
+<dd>
+periodic scan interval
+</dd>
+</dl>
+<a NAME="WifiNetworksWindow.on_periodicCheckBox_toggled" ID="WifiNetworksWindow.on_periodicCheckBox_toggled"></a>
+<h4>WifiNetworksWindow.on_periodicCheckBox_toggled</h4>
+<b>on_periodicCheckBox_toggled</b>(<i>checked</i>)
+
+<p>
+        Private slot handling the selection of a periodic scan.
+</p>
+<dl>
+
+<dt><i>checked</i> (bool)</dt>
+<dd>
+flag indicating a periodic scan
+</dd>
+</dl>
+<a NAME="WifiNetworksWindow.scanNetworks" ID="WifiNetworksWindow.scanNetworks"></a>
+<h4>WifiNetworksWindow.scanNetworks</h4>
+<b>scanNetworks</b>(<i></i>)
+
+<p>
+        Public method to ask the device for a network scan and display the result.
+</p>
+<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.WifiDialogs.WifiStatusDialog.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.WifiDialogs.WifiStatusDialog</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.MicroPython.WifiDialogs.WifiStatusDialog</h1>
+
+<p>
+Module implementing a dialog to show the WiFi status of the connected device.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiStatusDialog">WifiStatusDialog</a></td>
+<td>Class implementing a dialog to show the WiFi status of the connected device.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="WifiStatusDialog" ID="WifiStatusDialog"></a>
+<h2>WifiStatusDialog</h2>
+
+<p>
+    Class implementing a dialog to show the WiFi status of the connected device.
+</p>
+<h3>Derived from</h3>
+QDialog, Ui_WifiStatusDialog
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#WifiStatusDialog.__init__">WifiStatusDialog</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#WifiStatusDialog.__createHeader">__createHeader</a></td>
+<td>Private method to create a header item.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="WifiStatusDialog.__init__" ID="WifiStatusDialog.__init__"></a>
+<h4>WifiStatusDialog (Constructor)</h4>
+<b>WifiStatusDialog</b>(<i>clientStatus, apStatus, overallStatus, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>clientStatus</i> (dict)</dt>
+<dd>
+dictionary containing the WiFi status data of the
+            client interface
+</dd>
+<dt><i>apStatus</i> (dict)</dt>
+<dd>
+dictionary containing the WiFi status data of the
+            access point interface
+</dd>
+<dt><i>overallStatus</i> (dict)</dt>
+<dd>
+dictionary containing the overall WiFi status data
+</dd>
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="WifiStatusDialog.__createHeader" ID="WifiStatusDialog.__createHeader"></a>
+<h4>WifiStatusDialog.__createHeader</h4>
+<b>__createHeader</b>(<i>headerText</i>)
+
+<p>
+        Private method to create a header item.
+</p>
+<dl>
+
+<dt><i>headerText</i> (str)</dt>
+<dd>
+text for the header item
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+reference to the created header item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QTreeWidgetItem
+</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.Preferences.ConfigurationPages.MicroPythonPage.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.Preferences.ConfigurationPages.MicroPythonPage.html	Fri Mar 03 11:31:53 2023 +0100
@@ -63,6 +63,14 @@
 <td>Constructor</td>
 </tr>
 <tr>
+<td><a href="#MicroPythonPage.on_apShowPasswordButton_clicked">on_apShowPasswordButton_clicked</a></td>
+<td>Private slot to show or hide the WiFi Access Point password.</td>
+</tr>
+<tr>
+<td><a href="#MicroPythonPage.on_showPasswordButton_clicked">on_showPasswordButton_clicked</a></td>
+<td>Private slot to show or hide the WiFi client password.</td>
+</tr>
+<tr>
 <td><a href="#MicroPythonPage.save">save</a></td>
 <td>Public slot to save the MicroPython configuration.</td>
 </tr>
@@ -87,6 +95,34 @@
 reference to the parent widget
 </dd>
 </dl>
+<a NAME="MicroPythonPage.on_apShowPasswordButton_clicked" ID="MicroPythonPage.on_apShowPasswordButton_clicked"></a>
+<h4>MicroPythonPage.on_apShowPasswordButton_clicked</h4>
+<b>on_apShowPasswordButton_clicked</b>(<i>checked</i>)
+
+<p>
+        Private slot to show or hide the WiFi Access Point password.
+</p>
+<dl>
+
+<dt><i>checked</i> (bool)</dt>
+<dd>
+state of the button
+</dd>
+</dl>
+<a NAME="MicroPythonPage.on_showPasswordButton_clicked" ID="MicroPythonPage.on_showPasswordButton_clicked"></a>
+<h4>MicroPythonPage.on_showPasswordButton_clicked</h4>
+<b>on_showPasswordButton_clicked</b>(<i>checked</i>)
+
+<p>
+        Private slot to show or hide the WiFi client password.
+</p>
+<dl>
+
+<dt><i>checked</i> (bool)</dt>
+<dd>
+state of the button
+</dd>
+</dl>
 <a NAME="MicroPythonPage.save" ID="MicroPythonPage.save"></a>
 <h4>MicroPythonPage.save</h4>
 <b>save</b>(<i></i>)
--- a/src/eric7/Documentation/Source/index-eric7.EricNetwork.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/index-eric7.EricNetwork.html	Fri Mar 03 11:31:53 2023 +0100
@@ -36,6 +36,10 @@
 <td>Module implementing some helpers for Google mail.</td>
 </tr>
 <tr>
+<td><a href="eric7.EricNetwork.EricIPv4InputWidget.html">EricIPv4InputWidget</a></td>
+<td>Module implementing a widget to enter an IPv4 address.</td>
+</tr>
+<tr>
 <td><a href="eric7.EricNetwork.EricJsonClient.html">EricJsonClient</a></td>
 <td>Module implementing the JSON based client base class.</td>
 </tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Documentation/Source/index-eric7.MicroPython.Devices.MCUScripts.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.Devices.MCUScripts</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<h1>eric7.MicroPython.Devices.MCUScripts</h1>
+
+<p>
+Package containing scripts for copying to the micro controller board.
+</p>
+
+
+<h3>Modules</h3>
+<table>
+
+<tr>
+<td><a href="eric7.MicroPython.Devices.MCUScripts.esp32WiFiConnect.html">esp32WiFiConnect</a></td>
+<td></td>
+</tr>
+<tr>
+<td><a href="eric7.MicroPython.Devices.MCUScripts.picowWiFiConnect.html">picowWiFiConnect</a></td>
+<td></td>
+</tr>
+</table>
+</body></html>
\ No newline at end of file
--- a/src/eric7/Documentation/Source/index-eric7.MicroPython.Devices.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/index-eric7.MicroPython.Devices.html	Fri Mar 03 11:31:53 2023 +0100
@@ -22,6 +22,10 @@
 <td><a href="index-eric7.MicroPython.Devices.EspDialogs.html">EspDialogs</a></td>
 <td>Package implementing dialogs used by the EspDevices module.</td>
 </tr>
+<tr>
+<td><a href="index-eric7.MicroPython.Devices.MCUScripts.html">MCUScripts</a></td>
+<td>Package containing scripts for copying to the micro controller board.</td>
+</tr>
 </table>
 
 <h3>Modules</h3>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Documentation/Source/index-eric7.MicroPython.WifiDialogs.html	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.MicroPython.WifiDialogs</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<h1>eric7.MicroPython.WifiDialogs</h1>
+
+<p>
+Package implementing WiFi related dialogs.
+</p>
+
+
+<h3>Modules</h3>
+<table>
+
+<tr>
+<td><a href="eric7.MicroPython.WifiDialogs.WifiApConfigDialog.html">WifiApConfigDialog</a></td>
+<td>Module implementing a dialog to configure the Access Point interface.</td>
+</tr>
+<tr>
+<td><a href="eric7.MicroPython.WifiDialogs.WifiApStationsDialog.html">WifiApStationsDialog</a></td>
+<td>Module implementing a dialog showing the currently connected stations (clients).</td>
+</tr>
+<tr>
+<td><a href="eric7.MicroPython.WifiDialogs.WifiConnectionDialog.html">WifiConnectionDialog</a></td>
+<td>Module implementing a dialog to enter the parameters needed to connect to a WiFi network.</td>
+</tr>
+<tr>
+<td><a href="eric7.MicroPython.WifiDialogs.WifiController.html">WifiController</a></td>
+<td>Module implementing the WiFi related functionality.</td>
+</tr>
+<tr>
+<td><a href="eric7.MicroPython.WifiDialogs.WifiCountryDialog.html">WifiCountryDialog</a></td>
+<td>Module implementing a dialog to enter the country code for the WiFi interface.</td>
+</tr>
+<tr>
+<td><a href="eric7.MicroPython.WifiDialogs.WifiNetworksWindow.html">WifiNetworksWindow</a></td>
+<td>Module implementing a dialog showing the available WiFi networks.</td>
+</tr>
+<tr>
+<td><a href="eric7.MicroPython.WifiDialogs.WifiStatusDialog.html">WifiStatusDialog</a></td>
+<td>Module implementing a dialog to show the WiFi status of the connected device.</td>
+</tr>
+</table>
+</body></html>
\ No newline at end of file
--- a/src/eric7/Documentation/Source/index-eric7.MicroPython.html	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Documentation/Source/index-eric7.MicroPython.html	Fri Mar 03 11:31:53 2023 +0100
@@ -18,6 +18,10 @@
 <td><a href="index-eric7.MicroPython.Devices.html">Devices</a></td>
 <td>Package containing the device interface modules and device specific dialogs.</td>
 </tr>
+<tr>
+<td><a href="index-eric7.MicroPython.WifiDialogs.html">WifiDialogs</a></td>
+<td>Package implementing WiFi related dialogs.</td>
+</tr>
 </table>
 
 <h3>Modules</h3>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/EricNetwork/EricIPv4InputWidget.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,190 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a widget to enter an IPv4 address.
+"""
+
+import ipaddress
+
+from PyQt6.QtCore import QEvent, QRegularExpression, Qt, pyqtSignal, pyqtSlot
+from PyQt6.QtGui import QRegularExpressionValidator
+from PyQt6.QtWidgets import QWidget
+
+from eric7.EricGui import EricPixmapCache
+
+from .Ui_EricIPv4InputWidget import Ui_EricIPv4InputWidget
+
+
+class EricIPv4InputWidget(QWidget, Ui_EricIPv4InputWidget):
+    """
+    Class implementing a widget to enter an IPv4 address.
+
+    @signal addressChanged() emitted to indicate a change of the entered IPv4 address
+    """
+
+    addressChanged = pyqtSignal()
+
+    def __init__(self, parent=None):
+        """
+        Constructor
+
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+
+        self.clearButton.setIcon(EricPixmapCache.getIcon("clearLeft"))
+        self.clearButton.clicked.connect(self.__clear)
+
+        ipRange = r"(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])"
+
+        self.ip1Edit.setValidator(
+            QRegularExpressionValidator(QRegularExpression(ipRange))
+        )
+        self.ip2Edit.setValidator(
+            QRegularExpressionValidator(QRegularExpression(ipRange))
+        )
+        self.ip3Edit.setValidator(
+            QRegularExpressionValidator(QRegularExpression(ipRange))
+        )
+        self.ip4Edit.setValidator(
+            QRegularExpressionValidator(QRegularExpression(ipRange))
+        )
+
+        self.ip1Edit.installEventFilter(self)
+        self.ip2Edit.installEventFilter(self)
+        self.ip3Edit.installEventFilter(self)
+
+        self.ip1Edit.textChanged.connect(self.addressChanged)
+        self.ip2Edit.textChanged.connect(self.addressChanged)
+        self.ip3Edit.textChanged.connect(self.addressChanged)
+        self.ip4Edit.textChanged.connect(self.addressChanged)
+
+    def eventFilter(self, obj, evt):
+        """
+        Public method to filter pressing '.' to give focus to the next input field.
+
+        @param obj reference to the object
+        @type QObject
+        @param evt reference to the event object
+        @type QEvent
+        @return flag indicating, that the event was handled
+        @rtype bool
+        """
+        if evt.type() == QEvent.Type.KeyPress and evt.text() == ".":
+            if obj is self.ip1Edit:
+                nextWidget = self.ip2Edit
+            elif obj is self.ip2Edit:
+                nextWidget = self.ip3Edit
+            elif obj is self.ip3Edit:
+                nextWidget = self.ip4Edit
+            else:
+                nextWidget = None
+            if nextWidget:
+                nextWidget.setFocus(Qt.FocusReason.TabFocusReason)
+                return True
+
+        return super().eventFilter(obj, evt)
+
+    def hasAcceptableInput(self):
+        """
+        Public method to check, if the input is acceptable.
+
+        @return flag indicating acceptable input
+        @rtype bool
+        """
+        try:
+            ipaddress.IPv4Address(self.text())
+        except ipaddress.AddressValueError:
+            # leading zeros are not allowed
+            return False
+
+        return (
+            self.ip1Edit.hasAcceptableInput()
+            and self.ip2Edit.hasAcceptableInput()
+            and self.ip3Edit.hasAcceptableInput()
+            and self.ip4Edit.hasAcceptableInput()
+        )
+
+    def text(self):
+        """
+        Public method to get the IPv4 address as a string.
+
+        @return IPv4 address
+        @rtype str
+        """
+        return "{0}.{1}.{2}.{3}".format(
+            self.ip1Edit.text(),
+            self.ip2Edit.text(),
+            self.ip3Edit.text(),
+            self.ip4Edit.text(),
+        )
+
+    def setText(self, address):
+        """
+        Public method to set the IPv4 address given a string.
+
+        @param address IPv4 address
+        @type str
+        @exception ValueError raised to indicate an invalid IPv4 address
+        """
+        if address:
+            try:
+                ipaddress.IPv4Address(address)
+            except ipaddress.AddressValueError as err:
+                raise ValueError(str(err))
+
+            addressParts = address.split(".")
+            self.ip1Edit.setText(addressParts[0])
+            self.ip2Edit.setText(addressParts[1])
+            self.ip3Edit.setText(addressParts[2])
+            self.ip4Edit.setText(addressParts[3])
+        else:
+            self.clear()
+
+    def address(self):
+        """
+        Public method to get the IPv4 address as an ipaddress.IPv4Address object.
+
+        @return IPv4 address
+        @rtype ipaddress.IPv4Address
+        @exception ValueError raised to indicate an invalid IPv4 address
+        """
+        try:
+            return ipaddress.IPv4Address(self.text())
+        except ipaddress.AddressValueError as err:
+            raise ValueError(str(err))
+
+    def setAddress(self, address):
+        """
+        Public method to set the IPv4 address given an ipaddress.IPv4Address object.
+
+        @param address IPv4 address
+        @type ipaddress.IPv4Address
+        """
+        if address:
+            self.setText(str(address))
+        else:
+            self.clear()
+
+    @pyqtSlot()
+    def clear(self):
+        """
+        Public slot to clear the input fields.
+        """
+        self.ip1Edit.clear()
+        self.ip2Edit.clear()
+        self.ip3Edit.clear()
+        self.ip4Edit.clear()
+
+    @pyqtSlot()
+    def __clear(self):
+        """
+        Private slot to handle the clear button press.
+        """
+        self.clear()
+        self.ip1Edit.setFocus(Qt.FocusReason.OtherFocusReason)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/EricNetwork/EricIPv4InputWidget.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>EricIPv4InputWidget</class>
+ <widget class="QWidget" name="EricIPv4InputWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>283</width>
+    <height>26</height>
+   </rect>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QLineEdit" name="ip1Edit">
+     <property name="maximumSize">
+      <size>
+       <width>50</width>
+       <height>16777215</height>
+      </size>
+     </property>
+     <property name="maxLength">
+      <number>3</number>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string> . </string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLineEdit" name="ip2Edit">
+     <property name="maximumSize">
+      <size>
+       <width>50</width>
+       <height>16777215</height>
+      </size>
+     </property>
+     <property name="maxLength">
+      <number>3</number>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string> . </string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLineEdit" name="ip3Edit">
+     <property name="maximumSize">
+      <size>
+       <width>50</width>
+       <height>16777215</height>
+      </size>
+     </property>
+     <property name="maxLength">
+      <number>3</number>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string> . </string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLineEdit" name="ip4Edit">
+     <property name="maximumSize">
+      <size>
+       <width>50</width>
+       <height>16777215</height>
+      </size>
+     </property>
+     <property name="maxLength">
+      <number>3</number>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QToolButton" name="clearButton">
+     <property name="toolTip">
+      <string>Press to clear the entered IPv4 address</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- a/src/eric7/MicroPython/BoardDataDialog.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/BoardDataDialog.py	Fri Mar 03 11:31:53 2023 +0100
@@ -186,7 +186,6 @@
 
         font = headerItem.font(0)
         font.setBold(True)
-
         headerItem.setFont(0, font)
 
         return headerItem
--- a/src/eric7/MicroPython/Devices/CircuitPythonDevices.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/Devices/CircuitPythonDevices.py	Fri Mar 03 11:31:53 2023 +0100
@@ -7,14 +7,18 @@
 Module implementing the device interface class for CircuitPython boards.
 """
 
+import ast
+import binascii
+import json
 import os
 import shutil
 
-from PyQt6.QtCore import QProcess, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtCore import QUrl, pyqtSlot
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QMenu
 
 from eric7 import Globals, Preferences
+from eric7.EricGui.EricOverrideCursor import EricOverrideCursor
 from eric7.EricWidgets import EricFileDialog, EricMessageBox
 from eric7.EricWidgets.EricApplication import ericApp
 from eric7.SystemUtilities import FileSystemUtilities
@@ -50,6 +54,8 @@
         """
         super().__init__(microPythonWidget, deviceType, parent)
 
+        self._submitMode = "paste"  # use 'paste' mode to avoid loosing state
+
         self.__boardName = boardName
         self.__workspace = self.__findWorkspace()
 
@@ -57,6 +63,27 @@
 
         self.__createCPyMenu()
 
+        self.__securityTranslations = {
+            "OPEN": self.tr("open", "open WiFi network"),
+            "WEP": "WEP",
+            "WPA_PSK": "WPA",
+            "WPA2_PSK": "WPA2",
+            "WPA_WPA2_PSK": "WPA/WPA2",
+            "WPA2_ENTERPRISE": "WPA2 (CCMP)",
+            "WPA3_PSK": "WPA3",
+            "WPA2_WPA3_PSK": "WPA2/WPA3",
+        }
+        self.__securityCode2AuthModeString = {
+            0: "[wifi.AuthMode.OPEN]",
+            1: "[wifi.AuthMode.WEP]",
+            2: "[wifi.AuthMode.WPA, wifi.AuthMode.PSK]",
+            3: "[wifi.AuthMode.WPA2, wifi.AuthMode.PSK]",
+            4: "[wifi.AuthMode.WPA, wifi.AuthMode.WPA2, wifi.AuthMode.PSK]",
+            5: "[wifi.AuthMode.WPA2, wifi.AuthMode.ENTERPRISE]",
+            6: "[wifi.AuthMode.WPA3, wifi.AuthMode.PSK]",
+            7: "[wifi.AuthMode.WPA2, wifi.AuthMode.WPA3, wifi.AuthMode.PSK]",
+        }
+
     def setConnected(self, connected):
         """
         Public method to set the connection state.
@@ -67,6 +94,9 @@
         if not connected and self.__libraryMenu.isTearOffMenuVisible():
             self.__libraryMenu.hideTearOffMenu()
 
+        if self.__flashMenu.isTearOffMenuVisible():
+            self.__flashMenu.hideTearOffMenu()
+
         super().setConnected(connected)
 
     def setButtons(self):
@@ -197,8 +227,8 @@
         """
         Private method to find the workspace directory.
 
-        @param silent flag indicating silent operations
-        @type bool
+        @param silent flag indicating silent operations (defaults to False)
+        @type bool (optional)
         @return workspace directory used for saving files
         @rtype str
         """
@@ -260,35 +290,62 @@
         self.__libraryMenu.aboutToShow.connect(self.__aboutToShowLibraryMenu)
         self.__libraryMenu.setTearOffEnabled(True)
 
+        self.__flashMenu = self.__createFlashMenus()
+
         self.__cpyMenu = QMenu(self.tr("CircuitPython Functions"))
-
         self.__cpyMenu.addAction(
             self.tr("Show CircuitPython Versions"), self.__showCircuitPythonVersions
         )
         self.__cpyMenu.addSeparator()
-
-        boardName = self.microPython.getCurrentBoard()
-        lBoardName = boardName.lower() if boardName else ""
-        if "teensy" in lBoardName:
-            # Teensy 4.0 and 4.1 don't support UF2 flashing
-            self.__cpyMenu.addAction(
-                self.tr("CircuitPython Flash Instructions"),
-                self.__showTeensyFlashInstructions,
-            )
-            self.__flashCpyAct = self.__cpyMenu.addAction(
-                self.tr("Flash CircuitPython Firmware"), self.__startTeensyLoader
-            )
-            self.__flashCpyAct.setToolTip(
-                self.tr(
-                    "Start the 'Teensy Loader' application to flash the Teensy device."
-                )
-            )
-        else:
-            self.__flashCpyAct = self.__cpyMenu.addAction(
-                self.tr("Flash CircuitPython Firmware"), self.__flashCircuitPython
-            )
+        self.__flashCpyAct = self.__cpyMenu.addMenu(self.__flashMenu)
         self.__cpyMenu.addSeparator()
         self.__cpyMenu.addMenu(self.__libraryMenu)
+        self.__cpyMenu.addSeparator()
+        self.__resetAct = self.__cpyMenu.addAction(
+            self.tr("Reset Device"), self.__resetDevice
+        )
+
+    def __createFlashMenus(self):
+        """
+        Private method to create the various menus to flash a CircuitPython firmware.
+
+        @return reference to the created top level flash menu
+        @rtype QMenu
+        """
+        menu = QMenu(self.tr("Flash CircuitPython Firmware"))
+        menu.setTearOffEnabled(True)
+
+        # UF2 devices
+        menu.addAction(self.tr("UF2 Device"), self.__flashCircuitPython)
+        menu.addSeparator()
+
+        # ESP32 specific submenu
+        self.__esp32FlashMenu = QMenu(self.tr("ESP32 Device"))
+        self.__esp32FlashMenu.addAction(self.tr("Erase Flash"), self.__esp32EraseFlash)
+        self.__esp32FlashMenu.addAction(
+            self.tr("Flash MicroPython Firmware"), self.__esp32FlashPython
+        )
+        self.__esp32FlashMenu.addSeparator()
+        self.__esp32FlashMenu.addAction(
+            self.tr("Flash Additional Firmware"), self.__esp32FlashAddons
+        )
+        menu.addMenu(self.__esp32FlashMenu)
+
+        # Teensy 4.0 and 4.1 specific submenu
+        self.__teensyFlashMenu = QMenu(self.tr("Teensy Device"))
+        self.__teensyFlashMenu.addAction(
+            self.tr("CircuitPython Flash Instructions"),
+            self.__showTeensyFlashInstructions,
+        )
+        act = self.__teensyFlashMenu.addAction(
+            self.tr("Start 'Teensy Loader'"), self.__startTeensyLoader
+        )
+        act.setToolTip(
+            self.tr("Start the 'Teensy Loader' application to flash the Teensy device.")
+        )
+        menu.addMenu(self.__teensyFlashMenu)
+
+        return menu
 
     def addDeviceMenuEntries(self, menu):
         """
@@ -297,9 +354,11 @@
         @param menu reference to the context menu
         @type QMenu
         """
+        connected = self.microPython.isConnected()
         linkConnected = self.microPython.isLinkConnected()
 
         self.__flashCpyAct.setEnabled(not linkConnected)
+        self.__resetAct.setEnabled(connected)
 
         menu.addMenu(self.__cpyMenu)
 
@@ -328,6 +387,17 @@
                 self.__updater.installCircup,
             )
 
+    @pyqtSlot()
+    def __resetDevice(self):
+        """
+        Private slot to reset the connected device.
+        """
+        if self.microPython.isConnected():
+            self.microPython.deviceInterface().execute(
+                "import microcontroller\nmicrocontroller.reset()\n",
+                mode=self._submitMode,
+            )
+
     def hasFlashMenuEntry(self):
         """
         Public method to check, if the device has its own flash menu entry.
@@ -347,41 +417,54 @@
         dlg = UF2FlashDialog(boardType="circuitpython")
         dlg.exec()
 
+    @pyqtSlot()
     def __showTeensyFlashInstructions(self):
         """
-        Private method to show a message box because Teensy does not support
+        Private slot to show a message box because Teensy does not support
         the UF2 bootloader yet.
         """
-        EricMessageBox.information(
-            self.microPython,
-            self.tr("Flash CircuitPython Firmware"),
-            self.tr(
-                """<p>Teensy 4.0 and Teensy 4.1 do not support the UF2"""
-                """ bootloader. Please use the 'Teensy Loader'"""
-                """ application to flash CircuitPython. Make sure you"""
-                """ downloaded the CircuitPython .hex file.</p>"""
-                """<p>See <a href="{0}">the PJRC Teensy web site</a>"""
-                """ for details.</p>"""
-            ).format("https://www.pjrc.com/teensy/loader.html"),
-        )
+        from .TeensyDevices import showTeensyFlashInstructions
 
+        showTeensyFlashInstructions()
+
+    @pyqtSlot()
     def __startTeensyLoader(self):
         """
-        Private method to start the 'Teensy Loader' application.
+        Private slot to start the 'Teensy Loader' application.
 
         Note: The application must be accessible via the application search path.
         """
-        ok, _ = QProcess.startDetached("teensy")
-        if not ok:
-            EricMessageBox.warning(
-                self.microPython,
-                self.tr("Start 'Teensy Loader'"),
-                self.tr(
-                    """<p>The 'Teensy Loader' application <b>teensy</b> could not"""
-                    """ be started. Ensure it is in the application search path or"""
-                    """ start it manually.</p>"""
-                ),
-            )
+        from .TeensyDevices import startTeensyLoader
+
+        startTeensyLoader()
+
+    @pyqtSlot()
+    def __esp32EraseFlash(self):
+        """
+        Private slot to erase the flash of an ESP32 device.
+        """
+        from .EspDevices import eraseFlash
+
+        eraseFlash(self.microPython.getCurrentPort())
+
+    @pyqtSlot()
+    def __esp32FlashPython(self):
+        """
+        Private slot to flash a MicroPython or CircuitPython firmware to an ESP32
+        device.
+        """
+        from .EspDevices import flashPythonFirmware
+
+        flashPythonFirmware(self.microPython.getCurrentPort())
+
+    @pyqtSlot()
+    def __esp32FlashAddons(self):
+        """
+        Private slot to flash additional firmware to an ESP32 device.
+        """
+        from .EspDevices import flashAddonFirmware
+
+        flashAddonFirmware(self.microPython.getCurrentPort())
 
     @pyqtSlot()
     def __showCircuitPythonVersions(self):
@@ -394,9 +477,10 @@
         reply = ui.networkAccessManager().head(request)
         reply.finished.connect(lambda: self.__cpyVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __cpyVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
@@ -525,6 +609,534 @@
             ),
         ]
 
+    ##################################################################
+    ## Methods below implement WiFi related methods
+    ##################################################################
+
+    def hasWifi(self):
+        """
+        Public method to check the availability of WiFi.
+
+        @return tuple containing a flag indicating the availability of WiFi
+            and the WiFi type (picow or pimoroni)
+        @rtype tuple of (bool, str)
+        @exception OSError raised to indicate an issue with the device
+        """
+        command = """
+def has_wifi():
+    try:
+        import wifi
+        if hasattr(wifi, 'radio'):
+            return True, 'circuitpython'
+    except ImportError:
+        pass
+
+    return False, ''
+
+print(has_wifi())
+del has_wifi
+"""
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            raise OSError(self._shortError(err))
+        return ast.literal_eval(out.decode("utf-8"))
+
+    def getWifiData(self):
+        """
+        Public method to get data related to the current WiFi status.
+
+        @return tuple of three dictionaries containing the WiFi status data
+            for the WiFi client, access point and overall data
+        @rtype tuple of (dict, dict, dict)
+        @exception OSError raised to indicate an issue with the device
+        """
+        command = """
+def wifi_status():
+    import binascii
+    import json
+    import wifi
+
+    r = wifi.radio
+
+    station = {
+        'active': r.enabled and r.ipv4_address is not None,
+        'connected': r.ipv4_address is not None,
+        'ifconfig': (
+            str(r.ipv4_address) if r.ipv4_address else'0.0.0.0',
+            str(r.ipv4_subnet) if r.ipv4_subnet else'0.0.0.0',
+            str(r.ipv4_gateway) if r.ipv4_gateway else'0.0.0.0',
+            str(r.ipv4_dns) if r.ipv4_dns else'0.0.0.0',
+        ),
+        'mac': binascii.hexlify(r.mac_address, ':').decode(),
+        'hostname': r.hostname,
+    }
+    try:
+        station['txpower'] = r.tx_power
+    except AttributeError:
+        pass
+    try:
+        if r.ap_info is not None:
+            station.update({
+                'ap_ssid': r.ap_info.ssid,
+                'ap_bssid': binascii.hexlify(r.ap_info.bssid, ':'),
+                'ap_rssi': r.ap_info.rssi,
+                'ap_channel': r.ap_info.channel,
+                'ap_country': r.ap_info.country,
+            })
+            authmode = r.ap_info.authmode
+            station['ap_security'] = (
+                '_'.join(str(x).split('.')[-1] for x in authmode)
+                if isinstance(authmode, list)
+                else authmode
+            )
+    except (NotImplementedError, AttributeError):
+        pass
+    print(json.dumps(station))
+
+    ap = {
+        'active': r.enabled and r.ipv4_address_ap is not None,
+        'connected': r.ipv4_address_ap is not None,
+        'ifconfig': (
+            str(r.ipv4_address_ap) if r.ipv4_address_ap else'0.0.0.0',
+            str(r.ipv4_subnet_ap) if r.ipv4_subnet_ap else'0.0.0.0',
+            str(r.ipv4_gateway_ap) if r.ipv4_gateway_ap else'0.0.0.0',
+            str(r.ipv4_dns) if r.ipv4_dns else'0.0.0.0',
+        ),
+        'mac': binascii.hexlify(r.mac_address_ap, ':').decode(),
+        'hostname': r.hostname,
+    }
+    try:
+        ap['txpower'] = r.tx_power
+    except AttributeError:
+        pass
+    print(json.dumps(ap))
+
+    overall = {
+        'active': r.enabled
+    }
+    print(json.dumps(overall))
+
+wifi_status()
+del wifi_status
+"""
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            raise OSError(self._shortError(err))
+
+        stationStr, apStr, overallStr = out.decode("utf-8").splitlines()
+        station = json.loads(stationStr)
+        ap = json.loads(apStr)
+        overall = json.loads(overallStr)
+        if "ap_security" in station:
+            try:
+                station["ap_security"] = self.__securityTranslations[
+                    station["ap_security"]
+                ]
+            except KeyError:
+                station["ap_security"] = self.tr("unknown ({0})").format(
+                    station["ap_security"]
+                )
+
+        return station, ap, overall
+
+    def connectWifi(self, ssid, password):
+        """
+        Public method to connect a device to a WiFi network.
+
+        @param ssid name (SSID) of the WiFi network
+        @type str
+        @param password password needed to connect
+        @type str
+        @return tuple containing the connection status and an error string
+        @rtype tuple of (bool, str)
+        """
+        command = """
+def connect_wifi(ssid, password):
+    import json
+    import wifi
+
+    r = wifi.radio
+    try:
+        r.start_station()
+        r.connect(ssid, password)
+        status = 'connected'
+    except Exception as exc:
+        status = str(exc)
+
+    print(json.dumps({{'connected': r.ipv4_address is not None, 'status': status}}))
+
+connect_wifi({0}, {1})
+del connect_wifi
+""".format(
+            repr(ssid),
+            repr(password if password else ""),
+        )
+
+        with EricOverrideCursor():
+            out, err = self._interface.execute(
+                command, mode=self._submitMode, timeout=15000
+            )
+        if err:
+            return False, err
+
+        result = json.loads(out.decode("utf-8").strip())
+        error = "" if result["connected"] else result["status"]
+
+        return result["connected"], error
+
+    def disconnectWifi(self):
+        """
+        Public method to disconnect a device from the WiFi network.
+
+        @return tuple containing a flag indicating success and an error string
+        @rtype tuple of (bool, str)
+        """
+        command = """
+def disconnect_wifi():
+    import json
+    import wifi
+
+    r = wifi.radio
+    try:
+        r.stop_station()
+        status = ''
+    except Exception as exc:
+        status = str(exc)
+
+    print(json.dumps({'success': status == '', 'status': status}))
+
+disconnect_wifi()
+del disconnect_wifi
+"""
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+
+        result = json.loads(out.decode("utf-8").strip())
+        return result["success"], result["status"]
+
+    def writeCredentials(self, ssid, password):
+        """
+        Public method to write the given credentials to the connected device and modify
+        the start script to connect automatically.
+
+        @param ssid SSID of the network to connect to
+        @type str
+        @param password password needed to authenticate
+        @type str
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        if not self.__deviceVolumeMounted():
+            return False, self.tr("The device volume is not available.")
+
+        workspace = self.getWorkspace()
+
+        if Globals.versionToTuple(self._deviceData["release"]) >= (8, 0, 0):
+            # CircuitPython >= 8.0.0: generate 'settings.toml' file
+            contents = (
+                'CIRCUITPY_WIFI_SSID = "{0}"\nCIRCUITPY_WIFI_PASSWORD = "{1}"\n'.format(
+                    ssid, password
+                )
+            )
+            filename = os.path.join(workspace, "settings.toml")
+            if os.path.exists(filename):
+                ok = EricMessageBox.yesNo(
+                    None,
+                    self.tr("Write WiFi Credentials"),
+                    self.tr(
+                        """<p>The file <b>{0}</b> exists already. Shall it be"""
+                        """ replaced?</p>"""
+                    ).format(filename),
+                    icon=EricMessageBox.Warning,
+                )
+                if not ok:
+                    return False, self.tr("Aborted")
+            try:
+                with open(filename, "w") as f:
+                    f.write(contents)
+                    return True, ""
+            except OSError as err:
+                return False, str(err)
+
+        else:
+            # CircuitPython < 8.0.0: generate a secrets.py script
+            # step 1: generate the secrets.py file
+            contents = (
+                'secrets = {{\n    "ssid": "{0}",\n    "password": "{1}",\n}}\n'.format(
+                    ssid, password
+                )
+            )
+            filename = os.path.join(workspace, "secrets.py")
+            if os.path.exists(filename):
+                ok = EricMessageBox.yesNo(
+                    None,
+                    self.tr("Write WiFi Credentials"),
+                    self.tr(
+                        """<p>The file <b>{0}</b> exists already. Shall it be"""
+                        """ replaced?</p>"""
+                    ).format(filename),
+                    icon=EricMessageBox.Warning,
+                )
+                if not ok:
+                    return False, self.tr("Aborted")
+            # step 2: create the auto-connect script (wifi_connect.py)
+            try:
+                with open(filename, "w") as f:
+                    f.write(contents)
+            except OSError as err:
+                return False, str(err)
+            scriptFile = os.path.join(
+                os.path.dirname(__file__), "MCUScripts", "circuitPy7WiFiConnect.py"
+            )
+            targetFile = os.path.join(workspace, "wifi_connect.py")
+            try:
+                shutil.copy2(scriptFile, targetFile)
+            except OSError as err:
+                return False, str(err)
+            # Note: code.py will not be modified because the connection will be
+            #       reset anyway
+            return True, ""
+
+    def removeCredentials(self):
+        """
+        Public method to remove the saved credentials from the connected device.
+
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        if not self.__deviceVolumeMounted():
+            return False, self.tr("The device volume is not available.")
+
+        workspace = self.getWorkspace()
+        for name in ("settings.toml", "secrets.py"):
+            filename = os.path.join(workspace, name)
+            if os.path.exists(filename):
+                os.remove(filename)
+
+        return True, ""
+
+    def checkInternet(self):
+        """
+        Public method to check, if the internet can be reached.
+
+        @return tuple containing a flag indicating reachability and an error string
+        @rtype tuple of (bool, str)
+        """
+        command = """
+def check_internet():
+    import ipaddress
+    import wifi
+
+    r = wifi.radio
+    if r.ipv4_address is not None:
+        ping = r.ping(ipaddress.IPv4Address("9.9.9.9"))
+        print(ping is not None)
+    else:
+        print(False)
+
+check_internet()
+del check_internet
+"""
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+
+        return out.decode("utf-8").strip() == "True", ""
+
+    def scanNetworks(self):
+        """
+        Public method to scan for available WiFi networks.
+
+        @return tuple containing the list of available networks as a tuple of 'Name',
+            'MAC-Address', 'channel', 'RSSI' and 'security' and an error string
+        @rtype tuple of (list of tuple of (str, str, int, int, str), str)
+        """
+        command = """
+def scan_networks():
+    import wifi
+
+    r = wifi.radio
+    network_list = []
+    enabled = r.enabled
+    if not enabled:
+        r.enabled = True
+    for net in r.start_scanning_networks():
+        network_list.append(
+            (net.ssid, net.bssid, net.channel, net.rssi,
+             '_'.join(str(x).split('.')[-1] for x in net.authmode))
+        )
+    r.stop_scanning_networks()
+    if not enabled:
+        r.enabled = False
+    print(network_list)
+
+scan_networks()
+del scan_networks
+"""
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=15000
+        )
+        if err:
+            return [], err
+
+        networksList = ast.literal_eval(out.decode("utf-8"))
+        networks = []
+        seenNetworks = []
+        for network in networksList:
+            if network[0]:
+                ssid = network[0]
+                mac = binascii.hexlify(network[1], ":").decode("utf-8")
+                channel = network[2]
+                rssi = network[3]
+                try:
+                    security = self.__securityTranslations[network[4]]
+                except KeyError:
+                    security = self.tr("unknown ({0})").format(network[4])
+                if (ssid, mac, channel) not in seenNetworks:
+                    seenNetworks.append((ssid, mac, channel))
+                    networks.append((ssid, mac, channel, rssi, security))
+
+        return networks, ""
+
+    def deactivateInterface(self, interface):
+        """
+        Public method to deactivate a given WiFi interface of the connected device.
+
+        Note: With CircuitPython it is not possible to deactivate the station and
+        access point interfaces separately.
+
+        @param interface designation of the interface to be deactivated (one of 'AP'
+            or 'STA')
+        @type str
+        @return tuple containg a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        @exception ValueError raised to indicate a wrong value for the interface type
+        """
+        if interface not in ("STA", "AP"):
+            raise ValueError(
+                "interface must be 'AP' or 'STA', got '{0}'".format(interface)
+            )
+
+        command = """
+def deactivate():
+    import wifi
+
+    wifi.radio.enabled = False
+    print(not wifi.radio.enabled)
+
+deactivate()
+del deactivate
+"""
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+        else:
+            return out.decode("utf-8").strip() == "True", ""
+
+    def startAccessPoint(self, ssid, security=None, password=None, ifconfig=None):
+        """
+        Public method to start the access point interface.
+
+        @param ssid SSID of the access point
+        @type str
+        @param security security method (defaults to None)
+        @type int (optional)
+        @param password password (defaults to None)
+        @type str (optional)
+        @param ifconfig IPv4 configuration for the access point if not default
+            (IPv4 address, netmask, gateway address, DNS server address)
+        @type tuple of (str, str, str, str)
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        if security is None or password is None:
+            security = 0
+            password = ""
+        authmode = self.__securityCode2AuthModeString[security]
+
+        if ifconfig:
+            return (
+                False,
+                self.tr(
+                    "CircuitPython does not support setting the IPv4 parameters of the"
+                    " WiFi access point."
+                ),
+            )
+
+        command = """
+def start_ap(ssid, password):
+    import wifi
+
+    r = wifi.radio
+    try:
+        r.start_ap(ssid, password, authmode={2})
+    except ValueError as exc:
+        print('Error:', str(exc))
+
+start_ap({0}, {1})
+del start_ap
+""".format(
+            repr(ssid), repr(password), authmode
+        )
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=15000
+        )
+        if err:
+            return False, err
+        elif out and out.startswith(b"Error:"):
+            return False, out.decode("utf-8").split(None, 1)[-1]
+        else:
+            return True, ""
+
+    def stopAccessPoint(self):
+        """
+        Public method to stop the access point interface.
+
+        @return tuple containg a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        command = """
+def stop_ap():
+    import wifi
+
+    r = wifi.radio
+    try:
+        r.stop_ap()
+    except NotImplementedError as exc:
+        print('Error:', str(exc))
+
+stop_ap()
+del stop_ap
+"""
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+        elif out and out.startswith(b"Error:"):
+            return False, out.decode("utf-8").split(None, 1)[-1]
+        else:
+            return True, ""
+
+    def getConnectedClients(self):
+        """
+        Public method to get a list of connected clients.
+
+        @return a tuple containing a list of tuples containing the client MAC-Address
+            and the RSSI (if supported and available) and an error message
+        @rtype tuple of ([(bytes, int)], str)
+        """
+        return (
+            [],
+            self.tr("CircuitPython does not support reporting of connected clients"),
+        )
+
 
 def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber):
     """
--- a/src/eric7/MicroPython/Devices/DeviceBase.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/Devices/DeviceBase.py	Fri Mar 03 11:31:53 2023 +0100
@@ -33,19 +33,19 @@
     the time on the board and getting board related data. Supported file system
     commands are:
     <ul>
-    <li>ls: directory listing</li>
+    <li>cd: change directory</li>
+    <li>fileSystemInfo: get information about the file system
+    <li>get: get a file from the connected device</li>
+    <li>getData: read data of a file of the connected device</li>
     <li>lls: directory listing with meta data</li>
-    <li>cd: change directory</li>
-    <li>pwd: get the current directory</li>
+    <li>ls: directory listing</li>
+    <li>mkdir: create a new directory</li>
     <li>put: copy a file to the connected device</li>
     <li>putData: write data to a file of the connected device</li>
-    <li>get: get a file from the connected device</li>
-    <li>getData: read data of a file of the connected device</li>
+    <li>pwd: get the current directory</li>
     <li>rm: remove a file from the connected device</li>
+    <li>rmdir: remove an empty directory</li>
     <li>rmrf: remove a file/directory recursively (like 'rm -rf' in bash)
-    <li>mkdir: create a new directory</li>
-    <li>rmdir: remove an empty directory</li>
-    <li>fileSystemInfo: get information about the file system
     </ul>
 
     Supported non file system commands are:
@@ -55,8 +55,25 @@
         information</li>
     <li>getModules: get a list of built-in modules</li>
     <li>getTime: get the current time</li>
+    <li>showTime: show the current time of the connected device</li>
     <li>syncTime: synchronize the time of the connected device</li>
-    <li>showTime: show the current time of the connected device</li>
+    </ul>
+
+    Supported WiFi commands are:
+    <ul>
+    <li>hasWifi: check, if the board has WiFi functionality</li>
+    <li>getWifiData: get WiFi status data</li>
+    <li>connectWifi: connect to a WiFi network</li>
+    <li>disconnectWifi: disconnect from a WiFi network</li>
+    <li>writeCredentials: save the WiFi credentials to the board and create
+        functionality to auto-connect at boot time</li>
+    <li>removeCredentials: remove the saved credentials</li>
+    <li>checkInternet: check, if internet access is possible</li>
+    <li>scanNetworks: scan for available WiFi networks</li>
+    <li>deactivateInterface: deactivate a WiFi interface</li>
+    <li>startAccessPoint: start an access point</li>
+    <li>stopAccessPoint: stop the access point</li>
+    <li>getConnectedClients: get a list of connected WiFi clients</li>
     </ul>
     """
 
@@ -78,6 +95,8 @@
         self.microPython = microPythonWidget
         self._deviceData = {}  # dictionary with essential device data
 
+        self._submitMode = "raw"  # default is 'raw' mode to submit commands
+
     def setConnected(self, connected):
         """
         Public method to set the connection state.
@@ -93,6 +112,9 @@
         if connected:
             with contextlib.suppress(OSError):
                 self._deviceData = self.__getDeviceData()
+                self._deviceData["wifi"], self._deviceData["wifi_type"] = self.hasWifi()
+                self._deviceData["bluetooth"] = self.hasBluetooth()
+                self._deviceData["ethernet"] = self.hasEthernet()
 
     def getDeviceType(self):
         """
@@ -103,14 +125,22 @@
         """
         return self._deviceType
 
-    def getDeviceData(self):
+    def getDeviceData(self, key=None):
         """
         Public method to get a copy of the determined device data.
 
+        @param key name of the data to get (None to get all data) (defaults to None)
+        @type str (optional)
         @return dictionary containing the essential device data
         @rtype dict
         """
-        return copy.deepcopy(self._deviceData)
+        if key is None:
+            return copy.deepcopy(self._deviceData)
+        else:
+            try:
+                return self._deviceData[key]
+            except KeyError:
+                return None
 
     def checkDeviceData(self, quiet=True):
         """
@@ -129,7 +159,7 @@
             if not quiet:
                 EricMessageBox.critical(
                     None,
-                    self.tr("Show MicroPython Versions"),
+                    self.tr("Device Data Not Available"),
                     self.tr(
                         """<p>The device data is not available. Try to connect to the"""
                         """ device again. Aborting...</p>"""
@@ -149,6 +179,15 @@
             and self._deviceData["mpy_name"].lower() == "circuitpython"
         )
 
+    def submitMode(self):
+        """
+        Public method to get the submit mode of the device.
+
+        @return submit mode
+        @rtype str (one of 'raw', 'paste')
+        """
+        return self._submitMode
+
     def setButtons(self):
         """
         Public method to enable the supported action buttons.
@@ -305,21 +344,25 @@
         @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._interface.executeAsync(commandSequence)
+        if self._submitMode == "raw":
+            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._interface.executeAsync(commandSequence)
+        elif self._submitMode == "paste":
+            commands = b"\n".join([c.encode("utf-8)") for c in commandsList])
+            commandSequence = ["@PasteOn@", commands]
+            self._interface.executeAsyncPaste(commandSequence)
 
     @pyqtSlot()
     def handleDataFlood(self):
@@ -413,10 +456,6 @@
         """
         return []
 
-    ##################################################################
-    ## Methods below implement the file system commands
-    ##################################################################
-
     def _shortError(self, error):
         """
         Protected method to create a shortened error message.
@@ -435,6 +474,10 @@
 
         return self.tr("Detected an error without indications.")
 
+    ##################################################################
+    ## Methods below implement the file system commands
+    ##################################################################
+
     def ls(self, dirname=""):
         """
         Public method to get a directory listing of the connected device.
@@ -452,7 +495,7 @@
 """.format(
             dirname
         )
-        out, err = self._interface.execute(command)
+        out, err = self._interface.execute(command, mode=self._submitMode)
         if err:
             raise OSError(self._shortError(err))
         return ast.literal_eval(out.decode("utf-8"))
@@ -504,7 +547,7 @@
 """.format(
             dirname, showHidden
         )
-        out, err = self._interface.execute(command)
+        out, err = self._interface.execute(command, mode=self._submitMode)
         if err:
             raise OSError(self._shortError(err))
         fileslist = ast.literal_eval(out.decode("utf-8"))
@@ -532,7 +575,7 @@
 """.format(
                 dirname
             )
-            out, err = self._interface.execute(command)
+            out, err = self._interface.execute(command, mode=self._submitMode)
             if err:
                 raise OSError(self._shortError(err))
 
@@ -549,7 +592,7 @@
 print(__os_.getcwd())
 del __os_
 """
-        out, err = self._interface.execute(command)
+        out, err = self._interface.execute(command, mode=self._submitMode)
         if err:
             raise OSError(self._shortError(err))
         return out.decode("utf-8").strip()
@@ -565,12 +608,16 @@
         if filename:
             command = """
 import os as __os_
-__os_.remove('{0}')
+try:
+    __os_.remove('{0}')
+except OSError as err:
+    if err.errno != 2:
+        raise err
 del __os_
 """.format(
                 filename
             )
-            out, err = self._interface.execute(command)
+            out, err = self._interface.execute(command, mode=self._submitMode)
             if err:
                 raise OSError(self._shortError(err))
 
@@ -617,7 +664,7 @@
 """.format(
                 name, recursive, force
             )
-            out, err = self._interface.execute(command)
+            out, err = self._interface.execute(command, mode=self._submitMode)
             if err:
                 raise OSError(self._shortError(err))
             return ast.literal_eval(out.decode("utf-8"))
@@ -640,7 +687,7 @@
 """.format(
                 dirname
             )
-            out, err = self._interface.execute(command)
+            out, err = self._interface.execute(command, mode=self._submitMode)
             if err:
                 raise OSError(self._shortError(err))
 
@@ -667,7 +714,7 @@
 """.format(
                 dirname
             )
-            out, err = self._interface.execute(command)
+            out, err = self._interface.execute(command, mode=self._submitMode)
             if err:
                 raise OSError(self._shortError(err))
 
@@ -729,7 +776,7 @@
         )
         command = "\n".join(commands)
 
-        out, err = self._interface.execute(command)
+        out, err = self._interface.execute(command, mode=self._submitMode)
         if err:
             raise OSError(self._shortError(err))
         return True
@@ -798,7 +845,7 @@
 """.format(
             deviceFileName
         )
-        out, err = self._interface.execute(command)
+        out, err = self._interface.execute(command, mode=self._submitMode)
         if err:
             raise OSError(self._shortError(err))
 
@@ -837,7 +884,7 @@
 print(fsinfo())
 del __os_, fsinfo
 """
-        out, err = self._interface.execute(command)
+        out, err = self._interface.execute(command, mode=self._submitMode)
         if err:
             raise OSError(self._shortError(err))
         infolist = ast.literal_eval(out.decode("utf-8"))
@@ -910,7 +957,7 @@
 print(res)
 del res, uname, __os_, __sys_
 """
-        out, err = self._interface.execute(command)
+        out, err = self._interface.execute(command, mode=self._submitMode)
         if err:
             raise OSError(self._shortError(err))
         return ast.literal_eval(out.decode("utf-8"))
@@ -1017,9 +1064,9 @@
     res['ulab'] = None
 
 print(res)
-del res, __os_, __sys_
+del res, __os_, __sys_, uname
 """
-        out, err = self._interface.execute(command)
+        out, err = self._interface.execute(command, mode=self._submitMode)
         if err:
             raise OSError(self._shortError(err))
         return ast.literal_eval(out.decode("utf-8"))
@@ -1033,7 +1080,7 @@
         @exception OSError raised to indicate an issue with the device
         """
         commands = ["help('modules')"]
-        out, err = self._interface.execute(commands)
+        out, err = self._interface.execute(commands, mode=self._submitMode)
         if err:
             raise OSError(self._shortError(err))
 
@@ -1075,7 +1122,7 @@
         del tm
     del __time_
 """
-        out, err = self._interface.execute(command)
+        out, err = self._interface.execute(command, mode=self._submitMode)
         if err:
             if b"NotImplementedError" in err:
                 return "&lt;unsupported&gt; &lt;unsupported&gt;"
@@ -1147,10 +1194,182 @@
                     now.tm_isdst,
                 ),
             )
-            out, err = self._interface.execute(command)
+            out, err = self._interface.execute(command, mode=self._submitMode)
             if err:
                 raise OSError(self._shortError(err))
 
+    ##################################################################
+    ## Methods below implement WiFi related methods
+    ##################################################################
+
+    def hasWifi(self):
+        """
+        Public method to check the availability of WiFi.
+
+        @return tuple containing a flag indicating the availability of WiFi
+            and the WiFi type (picow or pimoroni)
+        @rtype tuple of (bool, str)
+        """
+        return False, ""
+
+    def addDeviceWifiEntries(self, menu):
+        """
+        Public method to add device specific entries to the given menu.
+
+        @param menu reference to the context menu
+        @type QMenu
+        """
+        pass
+
+    def getWifiData(self):
+        """
+        Public method to get data related to the current WiFi status.
+
+        @return tuple of three dictionaries containing the WiFi status data
+            for the WiFi client, access point and overall data
+        @rtype tuple of (dict, dict, dict)
+        """
+        return {}, {}, {}
+
+    def connectWifi(self, ssid, password):
+        """
+        Public method to connect a device to a WiFi network.
+
+        @param ssid name (SSID) of the WiFi network
+        @type str
+        @param password password needed to connect
+        @type str
+        @return tuple containing the connection status and an error string
+        @rtype tuple of (bool, str)
+        """
+        return False, self.tr("Operation not supported.")
+
+    def disconnectWifi(self):
+        """
+        Public method to disconnect a device from the WiFi network.
+
+        @return tuple containing a flag indicating success and an error string
+        @rtype tuple of (bool, str)
+        """
+        return True, ""
+
+    def writeCredentials(self, ssid, password):
+        """
+        Public method to write the given credentials to the connected device and modify
+        the start script to connect automatically.
+
+        @param ssid SSID of the network to connect to
+        @type str
+        @param password password needed to authenticate
+        @type str
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        return False, ""
+
+    def removeCredentials(self):
+        """
+        Public method to remove the saved credentials from the connected device.
+
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        return False, ""
+
+    def checkInternet(self):
+        """
+        Public method to check, if the internet can be reached.
+
+        @return tuple containing a flag indicating reachability and an error string
+        @rtype tuple of (bool, str)
+        """
+        return False, ""
+
+    def scanNetworks(self):
+        """
+        Public method to scan for available WiFi networks.
+
+        @return tuple containing the list of available networks as a tuple of 'Name',
+            'MAC-Address', 'channel', 'RSSI' and 'security' and an error string
+        @rtype tuple of (list of tuple of (str, str, int, int, str), str)
+        """
+        return [], ""
+
+    def deactivateInterface(self, interface):
+        """
+        Public method to deactivate a given WiFi interface of the connected device.
+
+        @param interface designation of the interface to be deactivated (one of 'AP'
+            or 'STA')
+        @type str
+        @return tuple containg a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        return True, ""
+
+    def startAccessPoint(self, ssid, security=None, password=None, ifconfig=None):
+        """
+        Public method to start the access point interface.
+
+        @param ssid SSID of the access point
+        @type str
+        @param security security method (defaults to None)
+        @type int (optional)
+        @param password password (defaults to None)
+        @type str (optional)
+        @param ifconfig IPv4 configuration for the access point if not default
+            (IPv4 address, netmask, gateway address, DNS server address)
+        @type tuple of (str, str, str, str)
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        return False, ""
+
+    def stopAccessPoint(self):
+        """
+        Public method to stop the access point interface.
+
+        @return tuple containg a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        return True, ""
+
+    def getConnectedClients(self):
+        """
+        Public method to get a list of connected clients.
+
+        @return a tuple containing a list of tuples containing the client MAC-Address
+            and the RSSI (if supported and available) and an error message
+        @rtype tuple of ([(bytes, int)], str)
+        """
+        return [], ""
+
+    ##################################################################
+    ## Methods below implement Ethernet related methods
+    ##################################################################
+
+    def hasEthernet(self):
+        """
+        Public method to check the availability of Ethernet.
+
+        @return flag indicating the availability of Ethernet
+        @rtype bool
+        """
+        return False
+
+    ##################################################################
+    ## Methods below implement Bluetooth related methods
+    ##################################################################
+
+    def hasBluetooth(self):
+        """
+        Public method to check the availability of Bluetooth.
+
+        @return flag indicating the availability of Bluetooth
+        @rtype bool
+        """
+        return False
+
 
 #
 # eflag: noqa = M613
--- a/src/eric7/MicroPython/Devices/EspDevices.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/Devices/EspDevices.py	Fri Mar 03 11:31:53 2023 +0100
@@ -8,11 +8,17 @@
 boards.
 """
 
-from PyQt6.QtCore import QProcess, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+import ast
+import binascii
+import json
+import os
+
+from PyQt6.QtCore import QCoreApplication, QProcess, QUrl, pyqtSlot
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QDialog, QMenu
 
 from eric7 import Globals, Preferences
+from eric7.EricGui.EricOverrideCursor import EricOverrideCursor
 from eric7.EricWidgets import EricMessageBox
 from eric7.EricWidgets.EricApplication import ericApp
 from eric7.EricWidgets.EricProcessDialog import EricProcessDialog
@@ -43,6 +49,27 @@
 
         self.__createEsp32Submenu()
 
+        self.__statusTranslations = {
+            200: self.tr("beacon timeout"),
+            201: self.tr("no matching access point found"),
+            202: self.tr("authentication failed"),
+            203: self.tr("association failed"),
+            204: self.tr("handshake timeout"),
+            1000: self.tr("idle"),
+            1001: self.tr("connecting"),
+            1010: self.tr("connected"),
+        }
+        self.__securityTranslations = {
+            0: self.tr("open", "open WiFi network"),
+            1: "WEP",
+            2: "WPA",
+            3: "WPA2",
+            4: "WPA/WPA2",
+            5: "WPA2 (CCMP)",
+            6: "WPA3",
+            7: "WPA2/WPA3",
+        }
+
     def setButtons(self):
         """
         Public method to enable the supported action buttons.
@@ -203,102 +230,21 @@
         """
         Private slot to erase the device flash memory.
         """
-        ok = EricMessageBox.yesNo(
-            self.microPython,
-            self.tr("Erase Flash"),
-            self.tr("""Shall the flash of the selected device really be erased?"""),
-        )
-        if ok:
-            flashArgs = [
-                "-u",
-                "-m",
-                "esptool",
-                "--port",
-                self.microPython.getCurrentPort(),
-                "erase_flash",
-            ]
-            dlg = EricProcessDialog(
-                self.tr("'esptool erase_flash' Output"),
-                self.tr("Erase Flash"),
-                showProgress=True,
-            )
-            res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
-            if res:
-                dlg.exec()
+        eraseFlash(self.microPython.getCurrentPort())
 
     @pyqtSlot()
     def __flashMicroPython(self):
         """
         Private slot to flash a MicroPython firmware to the device.
         """
-        from .EspDialogs.EspFirmwareSelectionDialog import EspFirmwareSelectionDialog
-
-        dlg = EspFirmwareSelectionDialog()
-        if dlg.exec() == QDialog.DialogCode.Accepted:
-            chip, firmware, baudRate, flashMode, flashAddress = dlg.getData()
-            flashArgs = [
-                "-u",
-                "-m",
-                "esptool",
-                "--chip",
-                chip,
-                "--port",
-                self.microPython.getCurrentPort(),
-            ]
-            if baudRate != "115200":
-                flashArgs += ["--baud", baudRate]
-            flashArgs.append("write_flash")
-            if flashMode:
-                flashArgs += ["--flash_mode", flashMode]
-            flashArgs += [
-                flashAddress,
-                firmware,
-            ]
-            dlg = EricProcessDialog(
-                self.tr("'esptool write_flash' Output"),
-                self.tr("Flash MicroPython Firmware"),
-                showProgress=True,
-            )
-            res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
-            if res:
-                dlg.exec()
+        flashPythonFirmware(self.microPython.getCurrentPort())
 
     @pyqtSlot()
     def __flashAddons(self):
         """
         Private slot to flash some additional firmware images.
         """
-        from .EspDialogs.EspFirmwareSelectionDialog import EspFirmwareSelectionDialog
-
-        dlg = EspFirmwareSelectionDialog(addon=True)
-        if dlg.exec() == QDialog.DialogCode.Accepted:
-            chip, firmware, baudRate, flashMode, flashAddress = dlg.getData()
-            flashArgs = [
-                "-u",
-                "-m",
-                "esptool",
-                "--chip",
-                chip,
-                "--port",
-                self.microPython.getCurrentPort(),
-            ]
-            if baudRate != "115200":
-                flashArgs += ["--baud", baudRate]
-            flashArgs.append("write_flash")
-            if flashMode:
-                flashArgs += ["--flash_mode", flashMode]
-            flashArgs += [
-                flashAddress.lower(),
-                firmware,
-            ]
-            dlg = EricProcessDialog(
-                self.tr("'esptool write_flash' Output"),
-                self.tr("Flash Additional Firmware"),
-                showProgress=True,
-            )
-            res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
-            if res:
-                dlg.exec()
+        flashAddonFirmware(self.microPython.getCurrentPort())
 
     @pyqtSlot()
     def __backupFlash(self):
@@ -417,9 +363,10 @@
             reply = ui.networkAccessManager().head(request)
             reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
@@ -526,7 +473,7 @@
         """
         if self.microPython.isConnected():
             self.microPython.deviceInterface().execute(
-                "import machine\nmachine.reset()\n"
+                "import machine\nmachine.reset()\n", mode=self._submitMode
             )
         else:
             # perform a reset via esptool using flash_id command ignoring
@@ -619,6 +566,478 @@
         rtc.init(clock_time)
 """
 
+    ##################################################################
+    ## Methods below implement WiFi related methods
+    ##################################################################
+
+    def hasWifi(self):
+        """
+        Public method to check the availability of WiFi.
+
+        @return tuple containing a flag indicating the availability of WiFi
+            and the WiFi type (esp32)
+        @rtype tuple of (bool, str)
+        """
+        return True, "esp32"
+
+    def getWifiData(self):
+        """
+        Public method to get data related to the current WiFi status.
+
+        @return tuple of three dictionaries containing the WiFi status data
+            for the WiFi client, access point and overall data
+        @rtype tuple of (dict, dict, dict)
+        @exception OSError raised to indicate an issue with the device
+        """
+        command = """
+def wifi_status():
+    import ubinascii
+    import ujson
+    import network
+
+    wifi = network.WLAN(network.STA_IF)
+    station = {
+        'active': wifi.active(),
+        'connected': wifi.isconnected(),
+        'status': wifi.status(),
+        'ifconfig': wifi.ifconfig(),
+        'mac': ubinascii.hexlify(wifi.config('mac'), ':').decode(),
+    }
+    if wifi.active():
+        try:
+            station['txpower'] = wifi.config('txpower')
+        except ValueError:
+            pass
+    print(ujson.dumps(station))
+
+    wifi = network.WLAN(network.AP_IF)
+    ap = {
+        'active': wifi.active(),
+        'connected': wifi.isconnected(),
+        'status': wifi.status(),
+        'ifconfig': wifi.ifconfig(),
+        'mac': ubinascii.hexlify(wifi.config('mac'), ':').decode(),
+        'channel': wifi.config('channel'),
+        'essid': wifi.config('essid'),
+    }
+    if wifi.active():
+        try:
+            ap['txpower'] = wifi.config('txpower')
+        except ValueError:
+            pass
+    print(ujson.dumps(ap))
+
+    overall = {
+        'active': station['active'] or ap['active']
+    }
+    print(ujson.dumps(overall))
+
+wifi_status()
+del wifi_status
+"""
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            raise OSError(self._shortError(err))
+
+        stationStr, apStr, overallStr = out.decode("utf-8").splitlines()
+        station = json.loads(stationStr)
+        ap = json.loads(apStr)
+        overall = json.loads(overallStr)
+        try:
+            station["status"] = self.__statusTranslations[station["status"]]
+        except KeyError:
+            station["status"] = str(station["status"])
+        try:
+            ap["status"] = self.__statusTranslations[ap["status"]]
+        except KeyError:
+            ap["status"] = str(ap["status"])
+        return station, ap, overall
+
+    def connectWifi(self, ssid, password):
+        """
+        Public method to connect a device to a WiFi network.
+
+        @param ssid name (SSID) of the WiFi network
+        @type str
+        @param password password needed to connect
+        @type str
+        @return tuple containing the connection status and an error string
+        @rtype tuple of (bool, str)
+        """
+        command = """
+def connect_wifi(ssid, password):
+    import network
+    import ujson
+    from time import sleep
+
+    wifi = network.WLAN(network.STA_IF)
+    wifi.active(False)
+    wifi.active(True)
+    wifi.connect(ssid, password)
+    max_wait = 140
+    while max_wait and wifi.status() == network.STAT_CONNECTING:
+        max_wait -= 1
+        sleep(0.1)
+    status = wifi.status()
+    print(ujson.dumps({{'connected': wifi.isconnected(), 'status': status}}))
+
+connect_wifi({0}, {1})
+del connect_wifi
+""".format(
+            repr(ssid),
+            repr(password if password else ""),
+        )
+
+        with EricOverrideCursor():
+            out, err = self._interface.execute(
+                command, mode=self._submitMode, timeout=15000
+            )
+        if err:
+            return False, err
+
+        result = json.loads(out.decode("utf-8").strip())
+        if result["connected"]:
+            error = ""
+        else:
+            try:
+                error = self.__statusTranslations[result["status"]]
+            except KeyError:
+                error = str(result["status"])
+
+        return result["connected"], error
+
+    def disconnectWifi(self):
+        """
+        Public method to disconnect a device from the WiFi network.
+
+        @return tuple containing a flag indicating success and an error string
+        @rtype tuple of (bool, str)
+        """
+        command = """
+def disconnect_wifi():
+    import network
+    from time import sleep
+
+    wifi = network.WLAN(network.STA_IF)
+    wifi.disconnect()
+    wifi.active(False)
+    sleep(0.1)
+    print(not wifi.isconnected())
+
+disconnect_wifi()
+del disconnect_wifi
+"""
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+
+        return out.decode("utf-8").strip() == "True", ""
+
+    def writeCredentials(self, ssid, password):
+        """
+        Public method to write the given credentials to the connected device and modify
+        the start script to connect automatically.
+
+        @param ssid SSID of the network to connect to
+        @type str
+        @param password password needed to authenticate
+        @type str
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        nvsCommand = """
+def save_wifi_creds(ssid, password):
+    import esp32
+
+    nvs = esp32.NVS('wifi_creds')
+    nvs.set_blob('ssid', ssid)
+    nvs.set_blob('password', password)
+    nvs.commit()
+
+save_wifi_creds({0}, {1})
+del save_wifi_creds
+""".format(
+            repr(ssid), repr(password) if password else "''"
+        )
+        bootCommand = """
+def modify_boot():
+    add = True
+    try:
+        with open('/boot.py', 'r') as f:
+            for ln in f.readlines():
+                if 'wifi_connect' in ln:
+                    add = False
+                    break
+    except:
+        pass
+    if add:
+        with open('/boot.py', 'a') as f:
+            f.write('\\nimport wifi_connect\\n')
+    print(True)
+
+modify_boot()
+del modify_boot
+"""
+
+        out, err = self._interface.execute(nvsCommand, mode=self._submitMode)
+        if err:
+            return False, self.tr("Error saving credentials: {0}").format(err)
+
+        try:
+            # copy auto-connect file
+            self.put(
+                os.path.join(
+                    os.path.dirname(__file__), "MCUScripts", "esp32WiFiConnect.py"
+                ),
+                "/wifi_connect.py",
+            )
+        except OSError as err:
+            return False, self.tr("Error saving auto-connect script: {0}").format(err)
+
+        out, err = self._interface.execute(bootCommand, mode=self._submitMode)
+        if err:
+            return False, self.tr("Error modifying 'boot.py': {0}").format(err)
+
+        return True, ""
+
+    def removeCredentials(self):
+        """
+        Public method to remove the saved credentials from the connected device.
+
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        nvsCommand = """
+def delete_wifi_creds():
+    import esp32
+
+    nvs = esp32.NVS('wifi_creds')
+    try:
+        nvs.erase_key('ssid')
+        nvs.erase_key('password')
+        nvs.commit()
+    except OSError:
+        pass
+
+delete_wifi_creds()
+del delete_wifi_creds
+"""
+
+        out, err = self._interface.execute(nvsCommand, mode=self._submitMode)
+        if err:
+            return False, self.tr("Error deleting credentials: {0}").format(err)
+
+        return True, ""
+
+    def checkInternet(self):
+        """
+        Public method to check, if the internet can be reached.
+
+        @return tuple containing a flag indicating reachability and an error string
+        @rtype tuple of (bool, str)
+        """
+        command = """
+def check_internet():
+    import network
+    import socket
+
+    wifi = network.WLAN(network.STA_IF)
+    if wifi.isconnected():
+        s = socket.socket()
+        try:
+            s.connect(socket.getaddrinfo('quad9.net', 80)[0][-1])
+            s.close()
+            print(True)
+        except:
+            print(False)
+    else:
+        print(False)
+
+check_internet()
+del check_internet
+"""
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+
+        return out.decode("utf-8").strip() == "True", ""
+
+    def scanNetworks(self):
+        """
+        Public method to scan for available WiFi networks.
+
+        @return tuple containing the list of available networks as a tuple of 'Name',
+            'MAC-Address', 'channel', 'RSSI' and 'security' and an error string
+        @rtype tuple of (list of tuple of (str, str, int, int, str), str)
+        """
+        command = """
+def scan_networks():
+    import network
+
+    wifi = network.WLAN(network.STA_IF)
+    active = wifi.active()
+    if not active:
+        wifi.active(True)
+    network_list = wifi.scan()
+    if not active:
+        wifi.active(False)
+    print(network_list)
+
+scan_networks()
+del scan_networks
+"""
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=15000
+        )
+        if err:
+            return [], err
+
+        networksList = ast.literal_eval(out.decode("utf-8"))
+        networks = []
+        for network in networksList:
+            if network[0]:
+                ssid = network[0].decode("utf-8")
+                mac = binascii.hexlify(network[1], ":").decode("utf-8")
+                channel = network[2]
+                rssi = network[3]
+                try:
+                    security = self.__securityTranslations[network[4]]
+                except KeyError:
+                    security = self.tr("unknown ({0})").format(network[4])
+                networks.append((ssid, mac, channel, rssi, security))
+
+        return networks, ""
+
+    def deactivateInterface(self, interface):
+        """
+        Public method to deactivate a given WiFi interface of the connected device.
+
+        @param interface designation of the interface to be deactivated (one of 'AP'
+            or 'STA')
+        @type str
+        @return tuple containg a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        @exception ValueError raised to indicate a wrong value for the interface type
+        """
+        if interface not in ("STA", "AP"):
+            raise ValueError(
+                "interface must be 'AP' or 'STA', got '{0}'".format(interface)
+            )
+
+        command = """
+def deactivate():
+    import network
+    from time import sleep
+
+    wifi = network.WLAN(network.{0}_IF)
+    wifi.active(False)
+    sleep(0.1)
+    print(not wifi.active())
+
+deactivate()
+del deactivate
+""".format(
+            interface
+        )
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+        else:
+            return out.decode("utf-8").strip() == "True", ""
+
+    def startAccessPoint(self, ssid, security=None, password=None, ifconfig=None):
+        """
+        Public method to start the access point interface.
+
+        @param ssid SSID of the access point
+        @type str
+        @param security security method (defaults to None)
+        @type int (optional)
+        @param password password (defaults to None)
+        @type str (optional)
+        @param ifconfig IPv4 configuration for the access point if not default
+            (IPv4 address, netmask, gateway address, DNS server address)
+        @type tuple of (str, str, str, str)
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        if security is None or password is None:
+            security = 0
+            password = ""
+        if security > 4:
+            security = 4  # security >4 cause an error thrown by the ESP32
+
+        command = """
+def start_ap(ssid, authmode, password, ifconfig):
+    import network
+
+    ap = network.WLAN(network.AP_IF)
+    ap.active(False)
+    if ifconfig:
+        ap.ifconfig(ifconfig)
+    ap.active(True)
+    try:
+        ap.config(ssid=ssid, authmode=authmode, password=password)
+    except:
+        ap.config(essid=ssid, authmode=authmode, password=password)
+
+start_ap({0}, {1}, {2}, {3})
+del start_ap
+""".format(
+            repr(ssid), security, repr(password), ifconfig
+        )
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=15000
+        )
+        if err:
+            return False, err
+        else:
+            return True, ""
+
+    def stopAccessPoint(self):
+        """
+        Public method to stop the access point interface.
+
+        @return tuple containg a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        return self.deactivateInterface("AP")
+
+    def getConnectedClients(self):
+        """
+        Public method to get a list of connected clients.
+
+        @return a tuple containing a list of tuples containing the client MAC-Address
+            and the RSSI (if supported and available) and an error message
+        @rtype tuple of ([(bytes, int)], str)
+        """
+        command = """
+def get_stations():
+    import network
+
+    ap = network.WLAN(network.AP_IF)
+    stations = ap.status('stations')
+    print(stations)
+
+get_stations()
+del get_stations
+"""
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=10000
+        )
+        if err:
+            return [], err
+
+        clientsList = ast.literal_eval(out.decode("utf-8"))
+        return clientsList, ""
+
 
 def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber):
     """
@@ -640,3 +1059,125 @@
     @rtype EspDevice
     """
     return EspDevice(microPythonWidget, deviceType)
+
+
+################################################################################
+## Functions below implement flashing related functionality needed elsewhere  ##
+## as well.                                                                   ##
+################################################################################
+
+
+@pyqtSlot()
+def eraseFlash(port):
+    """
+    Slot to erase the device flash memory.
+
+    @param port name of the serial port device to be used
+    @type str
+    """
+    ok = EricMessageBox.yesNo(
+        None,
+        QCoreApplication.translate("EspDevice", "Erase Flash"),
+        QCoreApplication.translate(
+            "EspDevice", """Shall the flash of the selected device really be erased?"""
+        ),
+    )
+    if ok:
+        flashArgs = [
+            "-u",
+            "-m",
+            "esptool",
+            "--port",
+            port,
+            "erase_flash",
+        ]
+        dlg = EricProcessDialog(
+            QCoreApplication.translate("EspDevice", "'esptool erase_flash' Output"),
+            QCoreApplication.translate("EspDevice", "Erase Flash"),
+            showProgress=True,
+        )
+        res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
+        if res:
+            dlg.exec()
+
+
+@pyqtSlot()
+def flashPythonFirmware(port):
+    """
+    Slot to flash a MicroPython firmware to the device.
+
+    @param port name of the serial port device to be used
+    @type str
+    """
+    from .EspDialogs.EspFirmwareSelectionDialog import EspFirmwareSelectionDialog
+
+    dlg = EspFirmwareSelectionDialog()
+    if dlg.exec() == QDialog.DialogCode.Accepted:
+        chip, firmware, baudRate, flashMode, flashAddress = dlg.getData()
+        flashArgs = [
+            "-u",
+            "-m",
+            "esptool",
+            "--chip",
+            chip,
+            "--port",
+            port,
+        ]
+        if baudRate != "115200":
+            flashArgs += ["--baud", baudRate]
+        flashArgs.append("write_flash")
+        if flashMode:
+            flashArgs += ["--flash_mode", flashMode]
+        flashArgs += [
+            flashAddress,
+            firmware,
+        ]
+        dlg = EricProcessDialog(
+            QCoreApplication.translate("EspDevice", "'esptool write_flash' Output"),
+            QCoreApplication.translate("EspDevice", "Flash µPy/CPy Firmware"),
+            showProgress=True,
+        )
+        res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
+        if res:
+            dlg.exec()
+
+
+@pyqtSlot()
+def flashAddonFirmware(port):
+    """
+    Slot to flash some additional firmware images.
+
+    @param port name of the serial port device to be used
+    @type str
+    """
+    from .EspDialogs.EspFirmwareSelectionDialog import EspFirmwareSelectionDialog
+
+    dlg = EspFirmwareSelectionDialog(addon=True)
+    if dlg.exec() == QDialog.DialogCode.Accepted:
+        chip, firmware, baudRate, flashMode, flashAddress = dlg.getData()
+        flashArgs = [
+            "-u",
+            "-m",
+            "esptool",
+            "--chip",
+            chip,
+            "--port",
+            port,
+        ]
+        if baudRate != "115200":
+            flashArgs += ["--baud", baudRate]
+        flashArgs.append("write_flash")
+        if flashMode:
+            flashArgs += ["--flash_mode", flashMode]
+        flashArgs += [
+            flashAddress.lower(),
+            firmware,
+        ]
+        dlg = EricProcessDialog(
+            QCoreApplication.translate("EspDevice", "'esptool write_flash' Output"),
+            QCoreApplication.translate("EspDevice", "Flash Additional Firmware"),
+            showProgress=True,
+        )
+        res = dlg.startProcess(PythonUtilities.getPythonExecutable(), flashArgs)
+        if res:
+            dlg.exec()
--- a/src/eric7/MicroPython/Devices/EspDialogs/EspFirmwareSelectionDialog.ui	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/Devices/EspDialogs/EspFirmwareSelectionDialog.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -11,7 +11,7 @@
    </rect>
   </property>
   <property name="windowTitle">
-   <string>Flash MicroPython Firmware</string>
+   <string>Flash µPy/CPy Firmware</string>
   </property>
   <property name="sizeGripEnabled">
    <bool>true</bool>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/Devices/MCUScripts/__init__.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Package containing scripts for copying to the micro controller board.
+"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/Devices/MCUScripts/circuitPy7WiFiConnect.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,23 @@
+try:
+    from secrets import secrets
+
+    def connectWiFi():
+        import wifi
+
+        print("Connecting WiFi to '{0}' ...".format(secrets["ssid"]))
+        wifi.radio.start_station()
+        try:
+            wifi.radio.connect(
+                secrets["ssid"],
+                "" if secrets["password"] is None else secrets["password"]
+            )
+        except Exception as exc:
+            print("WiFi connection failed:", str(exc))
+        if wifi.radio.ipv4_address is None:
+            print("WiFi connection failed")
+        else:
+            print("WiFi connected:", wifi.radio.ipv4_address)
+
+    connectWiFi()
+except ImportError:
+    print("WiFi secrets are kept in 'secrets.py', please add them there!")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/Devices/MCUScripts/esp32WiFiConnect.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,27 @@
+def connectWiFi():
+    import esp32
+    import network
+    from time import sleep
+
+    try:
+        nvs = esp32.NVS("wifi_creds")
+        buf = bytearray(1024)
+        size = nvs.get_blob("ssid", buf)
+        ssid = buf[:size].decode()
+        size = nvs.get_blob("password", buf)
+        password = buf[:size].decode()
+
+        wifi = network.WLAN(network.STA_IF)
+        wifi.active(False)
+        wifi.active(True)
+        wifi.connect(ssid, password)
+        max_wait = 140
+        print("Connecting WiFi to '{0}'...".format(ssid))
+        while max_wait and wifi.status() == network.STAT_CONNECTING:
+            max_wait -= 1
+            sleep(0.1)
+        print("Connection status:", wifi.isconnected())
+    except:
+        print("WiFi secrets are kept in NVM. Please store them there!")
+
+connectWiFi()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/Devices/MCUScripts/mpyWiFiConnect.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,26 @@
+try:
+    import secrets
+
+    def connectWiFi():
+        import network
+        from time import sleep
+
+        print("Connecting WiFi to '{0}' ...".format(secrets.WIFI_SSID))
+        wifi = network.WLAN(network.STA_IF)
+        wifi.active(False)
+        wifi.active(True)
+        wifi.connect(secrets.WIFI_SSID, secrets.WIFI_KEY if secrets.WIFI_KEY else None)
+        max_wait = 140
+        while max_wait:
+            if wifi.status() < 0 or wifi.status() >= 3:
+                break
+            max_wait -= 1
+            sleep(0.1)
+        if wifi.isconnected():
+            print("WiFi connected:", wifi.ifconfig())
+        else:
+            print("WiFi connection failed")
+
+    connectWiFi()
+except ImportError:
+    print("WiFi secrets are kept in 'secrets.py', please add them there!")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/Devices/MCUScripts/picowWiFiConnect.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,31 @@
+try:
+    import secrets
+
+    def connectWiFi():
+        import network
+        import rp2
+        from time import sleep
+
+        country = secrets.WIFI_COUNTRY
+        if country:
+            rp2.country(country)
+
+        print("Connecting WiFi to '{0}' ...".format(secrets.WIFI_SSID))
+        wifi = network.WLAN(network.STA_IF)
+        wifi.active(False)
+        wifi.active(True)
+        wifi.connect(secrets.WIFI_SSID, secrets.WIFI_KEY if secrets.WIFI_KEY else None)
+        max_wait = 140
+        while max_wait:
+            if wifi.status() < 0 or wifi.status() >= 3:
+                break
+            max_wait -= 1
+            sleep(0.1)
+        if wifi.isconnected():
+            print("WiFi connected:", wifi.ifconfig())
+        else:
+            print("WiFi connection failed")
+
+    connectWiFi()
+except ImportError:
+    print("WiFi secrets are kept in 'secrets.py', please add them there!")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/Devices/MCUScripts/pimoroniWiFiConnect.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,30 @@
+try:
+    import secrets
+
+    def connectWiFi():
+        import picowireless as pw
+        from time import sleep
+
+        print("Connecting WiFi to '{0}' ...".format(secrets.WIFI_SSID))
+        pw.init()
+        if bool(secrets.WIFI_KEY):
+            pw.wifi_set_passphrase(secrets.WIFI_SSID, secrets.WIFI_KEY)
+        else:
+            pw.wifi_set_network(secrets.WIFI_SSID)
+
+        max_wait = 140
+        while max_wait:
+            if pw.get_connection_status() == 3:
+                break
+            max_wait -= 1
+            sleep(0.1)
+        if pw.get_connection_status() == 3:
+            pw.set_led(0, 64, 0)
+            print("WiFi connected:", '.'.join(str(i) for i in pw.get_ip_address()))
+        else:
+            pw.set_led(64, 0, 0)
+            print("WiFi connection failed")
+
+    connectWiFi()
+except ImportError:
+    print("WiFi secrets are kept in 'secrets.py', please add them there!")
--- a/src/eric7/MicroPython/Devices/MicrobitDevices.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/Devices/MicrobitDevices.py	Fri Mar 03 11:31:53 2023 +0100
@@ -14,7 +14,7 @@
 import shutil
 
 from PyQt6.QtCore import QStandardPaths, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QMenu
 
 from eric7 import Globals, Preferences
@@ -54,6 +54,21 @@
 
         self.__createMicrobitMenu()
 
+    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
+        """
+        super().setConnected(connected)
+
+        if self.hasCircuitPython():
+            self._submitMode = "paste"
+
     def setButtons(self):
         """
         Public method to enable the supported action buttons.
@@ -409,9 +424,10 @@
                 reply = ui.networkAccessManager().head(request)
                 reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
@@ -504,12 +520,12 @@
         if self.getDeviceType() == "bbc_microbit":
             # BBC micro:bit
             self.microPython.deviceInterface().execute(
-                "import microbit\nmicrobit.reset()\n"
+                "import microbit\nmicrobit.reset()\n", mode=self._submitMode
             )
         else:
             # Calliope mini
             self.microPython.deviceInterface().execute(
-                "import calliope_mini\ncalliope_mini.reset()\n"
+                "import calliope_mini\ncalliope_mini.reset()\n", mode=self._submitMode
             )
 
     def getDocumentationUrl(self):
@@ -601,7 +617,7 @@
 print(__os_.listdir())
 del __os_
 """
-            out, err = self._interface.execute(command)
+            out, err = self._interface.execute(command, mode=self._submitMode)
             if err:
                 raise OSError(self._shortError(err))
             return ast.literal_eval(out.decode("utf-8"))
@@ -649,7 +665,7 @@
 """.format(
                 showHidden
             )
-            out, err = self._interface.execute(command)
+            out, err = self._interface.execute(command, mode=self._submitMode)
             if err:
                 raise OSError(self._shortError(err))
             fileslist = ast.literal_eval(out.decode("utf-8"))
--- a/src/eric7/MicroPython/Devices/PyBoardDevices.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/Devices/PyBoardDevices.py	Fri Mar 03 11:31:53 2023 +0100
@@ -10,7 +10,7 @@
 import os
 
 from PyQt6.QtCore import QStandardPaths, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QMenu
 
 from eric7 import Globals, Preferences
@@ -449,9 +449,10 @@
                 reply = ui.networkAccessManager().head(request)
                 reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
@@ -496,7 +497,8 @@
                 [
                     "import pyb",
                     "pyb.bootloader()",
-                ]
+                ],
+                mode=self._submitMode,
             )
             # simulate pressing the disconnect button
             self.microPython.on_connectButton_clicked()
--- a/src/eric7/MicroPython/Devices/RP2040Devices.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/Devices/RP2040Devices.py	Fri Mar 03 11:31:53 2023 +0100
@@ -8,11 +8,17 @@
 (e.g. Raspberry Pi Pico).
 """
 
+import ast
+import binascii
+import json
+import os
+
 from PyQt6.QtCore import QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
-from PyQt6.QtWidgets import QMenu
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
+from PyQt6.QtWidgets import QDialog, QMenu
 
 from eric7 import Globals, Preferences
+from eric7.EricGui.EricOverrideCursor import EricOverrideCursor
 from eric7.EricWidgets import EricMessageBox
 from eric7.EricWidgets.EricApplication import ericApp
 
@@ -41,6 +47,50 @@
 
         self.__createRP2040Menu()
 
+        self.__statusTranslations = {
+            "picow": {
+                -3: self.tr("authentication failed"),
+                -2: self.tr("no matching access point found"),
+                -1: self.tr("connection failed"),
+                0: self.tr("idle"),
+                1: self.tr("connecting"),
+                2: self.tr("connected, waiting for IP address"),
+                3: self.tr("connected"),
+            },
+            "picowireless": {
+                0: self.tr("idle"),
+                1: self.tr("no matching access point found"),
+                2: self.tr("network scan completed"),
+                3: self.tr("connected"),
+                4: self.tr("connection failed"),
+                5: self.tr("connection lost"),
+                6: self.tr("disconnected"),
+                7: self.tr("AP listening"),
+                8: self.tr("AP connected"),
+                9: self.tr("AP failed"),
+            },
+        }
+        # TODO: must be specific (picow, picowireless)
+        self.__securityTranslations = {
+            "picow": {
+                0: self.tr("open", "open WiFi network"),
+                1: "WEP",
+                2: "WPA",
+                3: "WPA2",
+                4: "WPA/WPA2",
+                5: "WPA2 (CCMP)",
+                6: "WPA3",
+                7: "WPA2/WPA3",
+            },
+            "picowireless": {
+                2: "WPA",
+                4: "WPA2 (CCMP)",
+                5: "WEP",
+                7: self.tr("open", "open WiFi network"),
+                8: self.tr("automatic"),
+            },
+        }
+
     def setButtons(self):
         """
         Public method to enable the supported action buttons.
@@ -136,6 +186,10 @@
         self.__flashMpyAct = self.__rp2040Menu.addAction(
             self.tr("Flash MicroPython Firmware"), self.__flashPython
         )
+        self.__rp2040Menu.addSeparator()
+        self.__resetAct = self.__rp2040Menu.addAction(
+            self.tr("Reset Device"), self.__resetDevice
+        )
 
     def addDeviceMenuEntries(self, menu):
         """
@@ -150,6 +204,7 @@
         self.__showMpyAct.setEnabled(connected)
         self.__bootloaderAct.setEnabled(connected)
         self.__flashMpyAct.setEnabled(not linkConnected)
+        self.__resetAct.setEnabled(connected)
 
         menu.addMenu(self.__rp2040Menu)
 
@@ -172,16 +227,18 @@
         dlg = UF2FlashDialog(boardType="rp2040")
         dlg.exec()
 
+    @pyqtSlot()
     def __activateBootloader(self):
         """
-        Private method to switch the board into 'bootloader' mode.
+        Private slot to switch the board into 'bootloader' mode.
         """
         if self.microPython.isConnected():
             self.microPython.deviceInterface().execute(
                 [
                     "import machine",
                     "machine.bootloader()",
-                ]
+                ],
+                mode=self._submitMode,
             )
             # simulate pressing the disconnect button
             self.microPython.on_connectButton_clicked()
@@ -214,9 +271,10 @@
                 reply = ui.networkAccessManager().head(request)
                 reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
@@ -269,6 +327,15 @@
             msg,
         )
 
+    @pyqtSlot()
+    def __resetDevice(self):
+        """
+        Private slot to reset the connected device.
+        """
+        self.microPython.deviceInterface().execute(
+            "import machine\nmachine.reset()\n", mode=self._submitMode
+        )
+
     def getDocumentationUrl(self):
         """
         Public method to get the device documentation URL.
@@ -339,6 +406,795 @@
     rtc.datetime(rtc_time[:7] + (0,))
 """
 
+    ##################################################################
+    ## Methods below implement WiFi related methods
+    ##################################################################
+
+    def addDeviceWifiEntries(self, menu):
+        """
+        Public method to add device specific entries to the given menu.
+
+        @param menu reference to the context menu
+        @type QMenu
+        """
+        menu.addSeparator()
+        menu.addAction(self.tr("Set Country"), self.__setCountry).setEnabled(
+            self._deviceData["wifi_type"] == "picow"
+        )
+
+    def hasWifi(self):
+        """
+        Public method to check the availability of WiFi.
+
+        @return tuple containing a flag indicating the availability of WiFi
+            and the WiFi type (picow or picowireless)
+        @rtype tuple of (bool, str)
+        @exception OSError raised to indicate an issue with the device
+        """
+        # picowireless:
+        # It seems to take up to 20 sec to detect, that no Pico Wireless Pack is
+        # attached. Therefore the command will timeout before.
+        command = """
+def has_wifi():
+    try:
+        import network
+        if hasattr(network, 'WLAN'):
+            return True, 'picow'
+    except ImportError:
+        try:
+            import picowireless as pw
+            try:
+                if pw.get_fw_version() != '':
+                    return True, 'picowireless'
+            except RuntimeError:
+                picowireless.init()
+                return True, 'picowireless'
+        except ImportError:
+            pass
+
+    return False, ''
+
+print(has_wifi())
+del has_wifi
+"""
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=10000
+        )
+        if err:
+            if not err.startswith(b"Timeout "):
+                raise OSError(self._shortError(err))
+            else:
+                return False  # pimoroni firmware loaded but no pico wireless present
+        return ast.literal_eval(out.decode("utf-8"))
+
+    def getWifiData(self):
+        """
+        Public method to get data related to the current WiFi status.
+
+        @return tuple of three dictionaries containing the WiFi status data
+            for the WiFi client, access point and overall data
+        @rtype tuple of (dict, dict, dict)
+        @exception OSError raised to indicate an issue with the device
+        """
+        if self._deviceData["wifi_type"] == "picow":
+            command = """
+def wifi_status():
+    import ubinascii
+    import ujson
+    import network
+    import rp2
+
+    wifi = network.WLAN(network.STA_IF)
+    station = {
+        'active': wifi.active(),
+        'connected': wifi.isconnected(),
+        'status': wifi.status(),
+        'ifconfig': wifi.ifconfig(),
+        'mac': ubinascii.hexlify(wifi.config('mac'), ':').decode(),
+        'channel': wifi.config('channel'),
+        'txpower': wifi.config('txpower'),
+        'country': rp2.country(),
+    }
+    print(ujson.dumps(station))
+
+    wifi = network.WLAN(network.AP_IF)
+    ap = {
+        'active': wifi.active(),
+        'connected': wifi.isconnected(),
+        'status': wifi.status(),
+        'ifconfig': wifi.ifconfig(),
+        'mac': ubinascii.hexlify(wifi.config('mac'), ':').decode(),
+        'channel': wifi.config('channel'),
+        'txpower': wifi.config('txpower'),
+        'essid': wifi.config('essid'),
+        'country': rp2.country(),
+    }
+    print(ujson.dumps(ap))
+
+    overall = {
+        'active': station['active'] or ap['active']
+    }
+    print(ujson.dumps(overall))
+
+wifi_status()
+del wifi_status
+"""
+        elif self._deviceData["wifi_type"] == "picowireless":
+            command = """
+def wifi_status():
+    import picowireless as pw
+    import ubinascii
+    import ujson
+
+    def ip_str(ip):
+        return '.'.join(str(i) for i in ip)
+
+    station = {
+        'active': pw.get_connection_status() not in (0, 7, 8, 9),
+        'connected': pw.get_connection_status() == 3,
+        'status': pw.get_connection_status(),
+        'ifconfig': (
+            ip_str(pw.get_ip_address()),
+            ip_str(pw.get_subnet_mask()),
+            ip_str(pw.get_gateway_ip()),
+            '0.0.0.0'
+        ),
+        'mac': ubinascii.hexlify(pw.get_mac_address(), ':').decode(),
+    }
+    if station['connected']:
+        station.update({
+            'ap_ssid': pw.get_current_ssid(),
+            'ap_bssid': ubinascii.hexlify(pw.get_current_bssid(), ':'),
+            'ap_rssi': pw.get_current_rssi(),
+            'ap_security': pw.get_current_encryption_type(),
+        })
+    print(ujson.dumps(station))
+
+    ap = {
+        'active': pw.get_connection_status() in (7, 8, 9),
+        'connected': pw.get_connection_status() == 8,
+        'status': pw.get_connection_status(),
+        'mac': ubinascii.hexlify(pw.get_mac_address(), ':').decode(),
+    }
+    if ap['active']:
+        ap['essid'] = pw.get_current_ssid()
+        ap['ifconfig'] = (
+            ip_str(pw.get_ip_address()),
+            ip_str(pw.get_subnet_mask()),
+            ip_str(pw.get_gateway_ip()),
+            '0.0.0.0'
+        )
+    print(ujson.dumps(ap))
+
+    overall = {
+        'active': pw.get_connection_status() != 0
+    }
+    print(ujson.dumps(overall))
+
+wifi_status()
+del wifi_status
+"""
+        else:
+            return super().getWifiData()
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            raise OSError(self._shortError(err))
+
+        stationStr, apStr, overallStr = out.decode("utf-8").splitlines()
+        station = json.loads(stationStr)
+        ap = json.loads(apStr)
+        overall = json.loads(overallStr)
+        if "status" in station:
+            # translate the numerical status to a string
+            try:
+                station["status"] = self.__statusTranslations[
+                    self._deviceData["wifi_type"]
+                ][station["status"]]
+            except KeyError:
+                station["status"] = str(station["status"])
+        if "status" in station:
+            # translate the numerical status to a string
+            try:
+                ap["status"] = self.__statusTranslations[self._deviceData["wifi_type"]][
+                    ap["status"]
+                ]
+            except KeyError:
+                ap["status"] = str(ap["status"])
+        if "ap_security" in station:
+            # translate the numerical AP security to a string
+            try:
+                station["ap_security"] = self.__securityTranslations[
+                    self._deviceData["wifi_type"]
+                ][station["ap_security"]]
+            except KeyError:
+                station["ap_security"] = self.tr("unknown ({0})").format(
+                    station["ap_security"]
+                )
+        return station, ap, overall
+
+    def connectWifi(self, ssid, password):
+        """
+        Public method to connect a device to a WiFi network.
+
+        @param ssid name (SSID) of the WiFi network
+        @type str
+        @param password password needed to connect
+        @type str
+        @return tuple containing the connection status and an error string
+        @rtype tuple of (bool, str)
+        """
+        if self._deviceData["wifi_type"] == "picow":
+            country = Preferences.getMicroPython("WifiCountry").upper()
+            command = """
+def connect_wifi(ssid, password, country):
+    import network
+    import rp2
+    import ujson
+    from time import sleep
+
+    rp2.country(country)
+
+    wifi = network.WLAN(network.STA_IF)
+    wifi.active(False)
+    wifi.active(True)
+    wifi.connect(ssid, password)
+    max_wait = 140
+    while max_wait:
+        if wifi.status() < 0 or wifi.status() >= 3:
+            break
+        max_wait -= 1
+        sleep(0.1)
+    status = wifi.status()
+    print(ujson.dumps({{'connected': wifi.isconnected(), 'status': status}}))
+
+connect_wifi({0}, {1}, {2})
+del connect_wifi
+""".format(
+                repr(ssid),
+                repr(password if password else ""),
+                repr(country if country else "XX"),
+            )
+        elif self._deviceData["wifi_type"] == "picowireless":
+            command = """
+def connect_wifi(ssid, password):
+    import picowireless as pw
+    import ujson
+    from time import sleep
+
+    pw.init()
+    if bool(password):
+        pw.wifi_set_passphrase(ssid, password)
+    else:
+        pw.wifi_set_network(ssid)
+
+    max_wait = 140
+    while max_wait:
+        if pw.get_connection_status() == 3:
+            break
+        max_wait -= 1
+        sleep(0.1)
+    status = pw.get_connection_status()
+    if status == 3:
+        pw.set_led(0, 64, 0)
+    else:
+        pw.set_led(64, 0, 0)
+    print(ujson.dumps({{'connected': status == 3, 'status': status}}))
+
+connect_wifi({0}, {1})
+del connect_wifi
+""".format(
+                repr(ssid),
+                repr(password if password else ""),
+            )
+        else:
+            return super().connectWifi(ssid, password)
+
+        with EricOverrideCursor():
+            out, err = self._interface.execute(
+                command, mode=self._submitMode, timeout=15000
+            )
+        if err:
+            return False, err
+
+        result = json.loads(out.decode("utf-8").strip())
+        if result["connected"]:
+            error = ""
+        else:
+            try:
+                error = self.__statusTranslations[self._deviceData["wifi_type"]][
+                    result["status"]
+                ]
+            except KeyError:
+                error = str(result["status"])
+
+        return result["connected"], error
+
+    def disconnectWifi(self):
+        """
+        Public method to disconnect a device from the WiFi network.
+
+        @return tuple containing a flag indicating success and an error string
+        @rtype tuple of (bool, str)
+        """
+        if self._deviceData["wifi_type"] == "picow":
+            command = """
+def disconnect_wifi():
+    import network
+    from time import sleep
+
+    wifi = network.WLAN(network.STA_IF)
+    wifi.disconnect()
+    wifi.active(False)
+    sleep(0.1)
+    print(not wifi.isconnected())
+
+disconnect_wifi()
+del disconnect_wifi
+"""
+        elif self._deviceData["wifi_type"] == "picowireless":
+            command = """
+def disconnect_wifi():
+    import picowireless as pw
+    from time import sleep
+
+    pw.disconnect()
+    sleep(0.1)
+    print(pw.get_connection_status() != 3)
+    pw.set_led(0, 0, 0)
+
+disconnect_wifi()
+del disconnect_wifi
+"""
+        else:
+            return super().disconnectWifi()
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+
+        return out.decode("utf-8").strip() == "True", ""
+
+    def writeCredentials(self, ssid, password):
+        """
+        Public method to write the given credentials to the connected device and modify
+        the start script to connect automatically.
+
+        @param ssid SSID of the network to connect to
+        @type str
+        @param password password needed to authenticate
+        @type str
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        command = """
+def modify_boot():
+    add = True
+    try:
+        with open('/boot.py', 'r') as f:
+            for ln in f.readlines():
+                if 'wifi_connect' in ln:
+                    add = False
+                    break
+    except:
+        pass
+    if add:
+        with open('/boot.py', 'a') as f:
+            f.write('\\nimport wifi_connect\\n')
+    print(True)
+
+modify_boot()
+del modify_boot
+"""
+
+        if self._deviceData["wifi_type"] == "picow":
+            country = Preferences.getMicroPython("WifiCountry").upper()
+            secrets = "WIFI_SSID = {0}\nWIFI_KEY = {1}\nWIFI_COUNTRY={2}".format(
+                repr(ssid),
+                repr(password) if password else '""',
+                repr(country) if country else '""',
+            )
+            wifiConnectFile = "picowWiFiConnect.py"
+        else:
+            secrets = "WIFI_SSID = {0}\nWIFI_KEY = {1}\n".format(
+                repr(ssid),
+                repr(password) if password else '""',
+            )
+            if self._deviceData["wifi_type"] == "picowireless":
+                wifiConnectFile = "pimoroniWiFiConnect.py"
+            else:
+                wifiConnectFile = "mpyWiFiConnect.py"
+        try:
+            # write secrets file
+            self.putData("/secrets.py", secrets.encode("utf-8"))
+            # copy auto-connect file
+            self.put(
+                os.path.join(os.path.dirname(__file__), "MCUScripts", wifiConnectFile),
+                "/wifi_connect.py",
+            )
+        except OSError as err:
+            return False, str(err)
+
+        # modify boot.py
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+
+        return out.decode("utf-8").strip() == "True", ""
+
+    def removeCredentials(self):
+        """
+        Public method to remove the saved credentials from the connected device.
+
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        try:
+            self.rm("/secrets.py")
+        except OSError as err:
+            return False, str(err)
+
+        return True, ""
+
+    def checkInternet(self):
+        """
+        Public method to check, if the internet can be reached.
+
+        @return tuple containing a flag indicating reachability and an error string
+        @rtype tuple of (bool, str)
+        """
+        if self._deviceData["wifi_type"] == "picow":
+            command = """
+def check_internet():
+    import network
+    import socket
+
+    wifi = network.WLAN(network.STA_IF)
+    if wifi.isconnected():
+        s = socket.socket()
+        try:
+            s.connect(socket.getaddrinfo('quad9.net', 80)[0][-1])
+            s.close()
+            print(True)
+        except:
+            print(False)
+    else:
+        print(False)
+
+check_internet()
+del check_internet
+"""
+        elif self._deviceData["wifi_type"] == "picowireless":
+            command = """
+def check_internet():
+    import picowireless as pw
+
+    if pw.get_connection_status() == 3:
+        res = pw.ping((9, 9, 9, 9), 300)
+        print(res >= 0)
+    else:
+        print(False)
+
+check_internet()
+del check_internet
+"""
+        else:
+            return super().checkInternet()
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=10000
+        )
+        if err:
+            return False, err
+
+        return out.decode("utf-8").strip() == "True", ""
+
+    def scanNetworks(self):
+        """
+        Public method to scan for available WiFi networks.
+
+        @return tuple containing the list of available networks as a tuple of 'Name',
+            'MAC-Address', 'channel', 'RSSI' and 'security' and an error string
+        @rtype tuple of (list of tuple of (str, str, int, int, str), str)
+        """
+        if self._deviceData["wifi_type"] == "picow":
+            country = Preferences.getMicroPython("WifiCountry").upper()
+            command = """
+def scan_networks():
+    import network
+    import rp2
+
+    rp2.country({0})
+
+    wifi = network.WLAN(network.STA_IF)
+    active = wifi.active()
+    if not active:
+        wifi.active(True)
+    network_list = wifi.scan()
+    if not active:
+        wifi.active(False)
+    print(network_list)
+
+scan_networks()
+del scan_networks
+""".format(
+                repr(country if country else "XX")
+            )
+
+        elif self._deviceData["wifi_type"] == "picowireless":
+            command = """
+def scan_networks():
+    import picowireless as pw
+
+    network_list = []
+    pw.init()
+    pw.start_scan_networks()
+    networks = pw.get_scan_networks()
+    for n in range(networks):
+        network_list.append((
+            pw.get_ssid_networks(n),
+            pw.get_bssid_networks(n),
+            pw.get_channel_networks(n),
+            pw.get_rssi_networks(n),
+            pw.get_enc_type_networks(n),
+        ))
+    print(network_list)
+
+scan_networks()
+del scan_networks
+"""
+        else:
+            return super().scanNetworks()
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=15000
+        )
+        if err:
+            return [], err
+
+        networksList = ast.literal_eval(out.decode("utf-8"))
+        networks = []
+        for network in networksList:
+            if network[0]:
+                ssid = (
+                    network[0].decode("utf-8")
+                    if isinstance(network[0], bytes)
+                    else network[0]
+                )
+                mac = (
+                    binascii.hexlify(network[1], ":").decode("utf-8")
+                    if network[1] is not None
+                    else ""
+                )
+                channel = network[2]
+                rssi = network[3]
+                try:
+                    security = self.__securityTranslations[
+                        self._deviceData["wifi_type"]
+                    ][network[4]]
+                except KeyError:
+                    security = self.tr("unknown ({0})").format(network[4])
+                networks.append((ssid, mac, channel, rssi, security))
+
+        return networks, ""
+
+    def deactivateInterface(self, interface):
+        """
+        Public method to deactivate a given WiFi interface of the connected device.
+
+        @param interface designation of the interface to be deactivated (one of 'AP'
+            or 'STA')
+        @type str
+        @return tuple containg a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        @exception ValueError raised to indicate a wrong value for the interface type
+        """
+        if interface not in ("STA", "AP"):
+            raise ValueError(
+                "interface must be 'AP' or 'STA', got '{0}'".format(interface)
+            )
+
+        if self._deviceData["wifi_type"] == "picow":
+            command = """
+def deactivate():
+    import network
+    from time import sleep
+
+    wifi = network.WLAN(network.{0}_IF)
+    wifi.active(False)
+    sleep(0.1)
+    print(not wifi.active())
+
+deactivate()
+del deactivate
+""".format(
+                interface
+            )
+        elif self._deviceData["wifi_type"] == "picowireless":
+            command = """
+def deactivate():
+    import picowireless as pw
+
+    pw.init()
+    print(True)
+
+deactivate()
+del deactivate
+"""
+        else:
+            return super().deactivateInterface(interface)
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            return False, err
+        else:
+            return out.decode("utf-8").strip() == "True", ""
+
+    def startAccessPoint(self, ssid, security=None, password=None, ifconfig=None):
+        """
+        Public method to start the access point interface.
+
+        @param ssid SSID of the access point
+        @type str
+        @param security security method (defaults to None)
+        @type int (optional)
+        @param password password (defaults to None)
+        @type str (optional)
+        @param ifconfig IPv4 configuration for the access point if not default
+            (IPv4 address, netmask, gateway address, DNS server address)
+        @type tuple of (str, str, str, str)
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        if security is None or password is None:
+            security = 0
+            password = ""
+
+        if self._deviceData["wifi_type"] == "picow":
+            country = Preferences.getMicroPython("WifiCountry").upper()
+            if security:
+                security = 4  # Pico W supports just WPA/WPA2
+            command = """
+def start_ap(ssid, security, password, ifconfig, country):
+    import network
+    import rp2
+    from time import sleep
+
+    rp2.country(country)
+
+    ap = network.WLAN(network.AP_IF)
+    ap.active(True)
+    if ifconfig:
+        ap.ifconfig(ifconfig)
+    ap.config(ssid=ssid, security=security, password=password)
+    sleep(0.1)
+    print(ap.isconnected())
+
+start_ap({0}, {1}, {2}, {3}, {4})
+del start_ap
+""".format(
+                repr(ssid),
+                security,
+                repr(password),
+                ifconfig,
+                repr(country if country else "XX"),
+            )
+        elif self._deviceData["wifi_type"] == "picowireless":
+            # AP is fixed at channel 6
+            command = """
+def start_ap(ssid, password):
+    import picowireless as pw
+
+    pw.init()
+    if bool(password):
+        res = pw.wifi_set_ap_passphrase(ssid, password, 6)
+    else:
+        res = pw.wifi_set_ap_network(ssid, 6)
+    status = pw.get_connection_status()
+    if status in (7, 8):
+        pw.set_led(0, 64, 0)
+    else:
+        pw.set_led(64, 0, 0)
+    print(res >= 0)
+
+start_ap({0}, {1})
+del start_ap
+""".format(
+                repr(ssid),
+                repr(password if password else ""),
+            )
+        else:
+            return super().startAccessPoint(ssid, security=security, password=password)
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=15000
+        )
+        if err:
+            return False, err
+        else:
+            return out.decode("utf-8").strip() == "True", ""
+
+    def stopAccessPoint(self):
+        """
+        Public method to stop the access point interface.
+
+        @return tuple containg a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        if self._deviceData["wifi_type"] in ("picow", "picowireless"):
+            return self.deactivateInterface("AP")
+        else:
+            return super().stopAccessPoint()
+
+    def getConnectedClients(self):
+        """
+        Public method to get a list of connected clients.
+
+        @return a tuple containing a list of tuples containing the client MAC-Address
+            and the RSSI (if supported and available) and an error message
+        @rtype tuple of ([(bytes, int)], str)
+        """
+        if self._deviceData["wifi_type"] == "picow":
+            command = """
+def get_stations():
+    import network
+
+    ap = network.WLAN(network.AP_IF)
+    stations = ap.status('stations')
+    print(stations)
+
+get_stations()
+del get_stations
+"""
+        elif self._deviceData["wifi_type"] == "picowireless":
+            return (
+                [],
+                self.tr(
+                    "Showing connected clients is not supported for 'pico wireless'."
+                ),
+            )
+        else:
+            return super().checkInternet()
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=10000
+        )
+        if err:
+            return [], err
+
+        clientsList = ast.literal_eval(out.decode("utf-8"))
+        return clientsList, ""
+
+    ############################################################################
+    ## RP2 only methods below
+    ############################################################################
+
+    @pyqtSlot()
+    def __setCountry(self):
+        """
+        Private slot to configure the country of the connected RP2040 device.
+
+        The country is the two letter country code.
+        """
+        from ..WifiDialogs.WifiCountryDialog import WifiCountryDialog
+
+        dlg = WifiCountryDialog()
+        if dlg.exec() == QDialog.DialogCode.Accepted:
+            country, remember = dlg.getCountry()
+            if remember:
+                Preferences.setMicroPython("WifiCountry", country)
+
+            command = """
+import rp2
+rp2.country({0})
+""".format(
+                repr(country)
+            )
+
+            out, err = self._interface.execute(command, mode=self._submitMode)
+            if err:
+                self.microPython.showError("rp2.country()", err)
+
 
 def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber):
     """
--- a/src/eric7/MicroPython/Devices/TeensyDevices.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/Devices/TeensyDevices.py	Fri Mar 03 11:31:53 2023 +0100
@@ -7,8 +7,8 @@
 Module implementing the device interface class for Teensy boards with MicroPython.
 """
 
-from PyQt6.QtCore import QProcess, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
+from PyQt6.QtCore import QCoreApplication, QProcess, QUrl, pyqtSlot
+from PyQt6.QtNetwork import QNetworkReply, QNetworkRequest
 from PyQt6.QtWidgets import QMenu
 
 from eric7 import Globals, Preferences
@@ -148,10 +148,10 @@
         )
         self.__teensyMenu.addSeparator()
         self.__teensyMenu.addAction(
-            self.tr("MicroPython Flash Instructions"), self.__showFlashInstructions
+            self.tr("MicroPython Flash Instructions"), showTeensyFlashInstructions
         )
         self.__flashMpyAct = self.__teensyMenu.addAction(
-            self.tr("Flash MicroPython Firmware"), self.__startTeensyLoader
+            self.tr("Flash MicroPython Firmware"), startTeensyLoader
         )
         self.__flashMpyAct.setToolTip(
             self.tr("Start the 'Teensy Loader' application to flash the Teensy device.")
@@ -195,9 +195,10 @@
                 reply = ui.networkAccessManager().head(request)
                 reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
 
+    @pyqtSlot(QNetworkReply)
     def __firmwareVersionResponse(self, reply):
         """
-        Private method handling the response of the latest version request.
+        Private slot handling the response of the latest version request.
 
         @param reply reference to the reply object
         @type QNetworkReply
@@ -232,40 +233,6 @@
             msg,
         )
 
-    def __showFlashInstructions(self):
-        """
-        Private method to show a message box with instruction to flash the Teensy.
-        """
-        EricMessageBox.information(
-            self.microPython,
-            self.tr("Flash MicroPython Firmware"),
-            self.tr(
-                """<p>Teensy 4.0 and Teensy 4.1 are flashed using the 'Teensy Loader'"""
-                """ application. Make sure you downloaded the MicroPython or"""
-                """ CircuitPython .hex file.</p>"""
-                """<p>See <a href="{0}">the PJRC Teensy web site</a>"""
-                """ for details.</p>"""
-            ).format("https://www.pjrc.com/teensy/loader.html"),
-        )
-
-    def __startTeensyLoader(self):
-        """
-        Private method to start the 'Teensy Loader' application.
-
-        Note: The application must be accessible via the application search path.
-        """
-        ok, _ = QProcess.startDetached("teensy")
-        if not ok:
-            EricMessageBox.warning(
-                self.microPython,
-                self.tr("Start 'Teensy Loader'"),
-                self.tr(
-                    """<p>The 'Teensy Loader' application <b>teensy</b> could not"""
-                    """ be started. Ensure it is in the application search path or"""
-                    """ start it manually.</p>"""
-                ),
-            )
-
     ##################################################################
     ## time related methods below
     ##################################################################
@@ -322,3 +289,43 @@
     @rtype PyBoardDevice
     """
     return TeensyDevice(microPythonWidget, deviceType)
+
+
+@pyqtSlot()
+def showTeensyFlashInstructions():
+    """
+    Slot to show a message box with instruction to flash the Teensy.
+    """
+    EricMessageBox.information(
+        None,
+        QCoreApplication.translate("TeensyDevice", "Flash MicroPython Firmware"),
+        QCoreApplication.translate(
+            "TeensyDevice",
+            """<p>Teensy 4.0 and Teensy 4.1 are flashed using the 'Teensy Loader'"""
+            """ application. Make sure you downloaded the MicroPython or"""
+            """ CircuitPython .hex file.</p>"""
+            """<p>See <a href="{0}">the PJRC Teensy web site</a>"""
+            """ for details.</p>""",
+        ).format("https://www.pjrc.com/teensy/loader.html"),
+    )
+
+
+@pyqtSlot()
+def startTeensyLoader():
+    """
+    Slot to start the 'Teensy Loader' application.
+
+    Note: The application must be accessible via the application search path.
+    """
+    ok, _ = QProcess.startDetached("teensy")
+    if not ok:
+        EricMessageBox.warning(
+            None,
+            QCoreApplication.translate("TeensyDevice", "Start 'Teensy Loader'"),
+            QCoreApplication.translate(
+                "TeensyDevice",
+                """<p>The 'Teensy Loader' application <b>teensy</b> could not"""
+                """ be started. Ensure it is in the application search path or"""
+                """ start it manually.</p>""",
+            ),
+        )
--- a/src/eric7/MicroPython/MicroPythonDeviceInterface.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/MicroPythonDeviceInterface.py	Fri Mar 03 11:31:53 2023 +0100
@@ -35,6 +35,9 @@
     executeAsyncFinished = pyqtSignal()
     dataReceived = pyqtSignal(bytes)
 
+    PasteModePrompt = b"=== "
+    TracebackMarker = b"Traceback (most recent call last):"
+
     def __init__(self, parent=None):
         """
         Constructor
@@ -107,6 +110,58 @@
         """
         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.
@@ -114,7 +169,7 @@
         Note: switching to raw mode is done with synchronous writes.
 
         @return flag indicating success
-        @@rtype bool
+        @rtype bool
         """
         if not self.__serial:
             return False
@@ -177,19 +232,19 @@
 
         # switch on raw mode
         self.__blockReadyRead = True
-        ok = self.__rawOn()
+        ok = self.__pasteOn()
         if not ok:
             self.__blockReadyRead = False
             return False
 
         # switch off raw mode
         QThread.msleep(10)
-        self.__rawOff()
+        self.__pasteOff()
         self.__blockReadyRead = False
 
         return True
 
-    def execute(self, commands):
+    def execute(self, commands, *, mode="raw", timeout=0):
         """
         Public method to send commands to the connected device and return the
         result.
@@ -198,6 +253,39 @@
 
         @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)
         """
@@ -231,6 +319,7 @@
                 )
                 ok = self.__serial.readUntil(b"OK")
                 if ok != b"OK":
+                    self.__blockReadyRead = False
                     return (
                         b"",
                         "Expected 'OK', got '{0}', followed by '{1}'".format(
@@ -239,7 +328,7 @@
                     )
 
                 # read until prompt
-                response = self.__serial.readUntil(b"\x04>")
+                response = self.__serial.readUntil(b"\x04>", timeout=timeout)
                 if self.__serial.hasTimedOut():
                     self.__blockReadyRead = False
                     return b"", b"Timeout while processing commands."
@@ -260,6 +349,84 @@
 
         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):
         """
         Public method to execute a series of commands over a period of time
@@ -274,3 +441,25 @@
             QTimer.singleShot(2, lambda: self.executeAsync(commandsList))
         else:
             self.executeAsyncFinished.emit()
+
+    def executeAsyncPaste(self, commandsList):
+        """
+        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 bytes
+        """
+        if commandsList:
+            self.__blockReadyRead = True
+            command = commandsList.pop(0)
+            if command == "@PasteOn@":
+                self.__pasteOn()
+            else:
+                self.__serial.write(command)
+                self.__serial.readUntil(command)
+            QTimer.singleShot(2, lambda: self.executeAsyncPaste(commandsList))
+        else:
+            self.__blockReadyRead = False
+            self.__pasteOff()
+            self.executeAsyncFinished.emit()
--- a/src/eric7/MicroPython/MicroPythonSerialPort.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/MicroPythonSerialPort.py	Fri Mar 03 11:31:53 2023 +0100
@@ -92,21 +92,27 @@
         """
         return self.__timedOut
 
-    def readUntil(self, expected=b"\n", size=None):
+    def readUntil(self, expected=b"\n", size=None, timeout=0):
         r"""
         Public method to read data until an expected sequence is found
         (default: \n) or a specific size is exceeded.
 
         @param expected expected bytes sequence
         @type bytes
-        @param size maximum data to be read
-        @type int
+        @param size maximum data to be read (defaults to None)
+        @type int (optional)
+        @param timeout timeout in milliseconds (0 for configured default)
+            (defaults to 0)
+        @type int (optional)
         @return bytes read from the device including the expected sequence
         @rtype bytes
         """
         data = bytearray()
         self.__timedOut = False
 
+        if timeout == 0:
+            timeout = self.__timeout
+
         t = QTime.currentTime()
         while True:
             QCoreApplication.processEvents(
@@ -119,7 +125,7 @@
                     break
                 if size is not None and len(data) >= size:
                     break
-            if t.msecsTo(QTime.currentTime()) > self.__timeout:
+            if t.msecsTo(QTime.currentTime()) > timeout:
                 self.__timedOut = True
                 break
 
--- a/src/eric7/MicroPython/MicroPythonWidget.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/MicroPythonWidget.py	Fri Mar 03 11:31:53 2023 +0100
@@ -41,6 +41,7 @@
 from . import Devices, UF2FlashDialog
 from .MicroPythonFileManagerWidget import MicroPythonFileManagerWidget
 from .Ui_MicroPythonWidget import Ui_MicroPythonWidget
+from .WifiDialogs.WifiController import WifiController
 
 try:
     from .MicroPythonGraphWidget import MicroPythonGraphWidget
@@ -223,6 +224,9 @@
 
         self.__ui = parent
 
+        self.__wifiController = WifiController(self, self)
+        self.__wifiMenu = None
+
         self.__superMenu = QMenu(self)
         self.__superMenu.aboutToShow.connect(self.__aboutToShowSuperMenu)
 
@@ -618,6 +622,9 @@
                 self.tr("Press to connect the selected device")
             )
 
+        if not connected and self.__wifiMenu and self.__wifiMenu.isTearOffMenuVisible():
+            self.__wifiMenu.hideTearOffMenu()
+
     def isConnected(self):
         """
         Public method to get the MicroPython device connection state.
@@ -745,9 +752,10 @@
             if pasteText:
                 pasteText = pasteText.replace("\n\r", "\r")
                 pasteText = pasteText.replace("\n", "\r")
-                self.__interface.isConnected() and self.__interface.write(
-                    pasteText.encode("utf-8")
-                )
+                if self.__interface.isConnected():
+                    self.__interface.write(b"\x05")
+                    self.__interface.write(pasteText.encode("utf-8"))
+                    self.__interface.write(b"\x04")
 
     def eventFilter(self, obj, evt):
         """
@@ -1115,6 +1123,15 @@
         boardName = self.deviceTypeComboBox.currentData(self.DeviceBoardRole)
         return boardName
 
+    def getDevice(self):
+        """
+        Public method to get a reference to the current device.
+
+        @return reference to the current device
+        @rtype BaseDevice
+        """
+        return self.__device
+
     def getDeviceWorkspace(self):
         """
         Public method to get the workspace directory of the device.
@@ -1444,6 +1461,14 @@
             else:
                 downloadMenu = None
 
+        # prepare the WiFi menu
+        if self.__device and self.__connected and self.__device.getDeviceData("wifi"):
+            if self.__wifiMenu is not None:
+                self.__wifiMenu.deleteLater()
+            self.__wifiMenu = self.__wifiController.createMenu(self.__superMenu)
+        else:
+            self.__wifiMenu = None
+
         # populate the super menu
         hasTime = self.__device.hasTimeCommands() if self.__device else False
 
@@ -1487,6 +1512,9 @@
         if self.__device:
             self.__device.addDeviceMenuEntries(self.__superMenu)
             self.__superMenu.addSeparator()
+            if self.__wifiMenu is not None:
+                self.__superMenu.addMenu(self.__wifiMenu)
+                self.__superMenu.addSeparator()
             if downloadMenu is None:
                 # generic download action
                 self.__superMenu.addAction(
@@ -1593,7 +1621,7 @@
             dlg = BoardDataDialog(boardInfo)
             dlg.exec()
         except Exception as exc:
-            self.__showError("getBoardInformation()", str(exc))
+            self.showError("getBoardInformation()", str(exc))
 
     @pyqtSlot()
     def __synchronizeTime(self, quiet=False):
@@ -1623,7 +1651,7 @@
                             + self.__getDeviceTime(),
                         )
             except Exception as exc:
-                self.__showError("syncTime()", str(exc))
+                self.showError("syncTime()", str(exc))
 
     def __getDeviceTime(self):
         """
@@ -1650,7 +1678,7 @@
                         dateTimeString.strip()
                     )
             except Exception as exc:
-                self.__showError("getTime()", str(exc))
+                self.showError("getTime()", str(exc))
                 return ""
         else:
             return ""
@@ -1727,11 +1755,11 @@
                     ).format(localdate, localtime, deviceDateTimeString.strip()),
                 )
         except Exception as exc:
-            self.__showError("getTime()", str(exc))
+            self.showError("getTime()", str(exc))
 
-    def __showError(self, method, error):
+    def showError(self, method, error):
         """
-        Private method to show some error message.
+        Public method to show some error message.
 
         @param method name of the method the error occured in
         @type str
@@ -1994,4 +2022,4 @@
                 )
                 dlg.show()
             except Exception as exc:
-                self.__showError("getModules()", str(exc))
+                self.showError("getModules()", str(exc))
--- a/src/eric7/MicroPython/UF2FlashDialog.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/UF2FlashDialog.py	Fri Mar 03 11:31:53 2023 +0100
@@ -13,7 +13,7 @@
 
 from PyQt6.QtCore import QCoreApplication, QEventLoop, Qt, QThread, pyqtSlot
 from PyQt6.QtSerialPort import QSerialPortInfo
-from PyQt6.QtWidgets import QDialog
+from PyQt6.QtWidgets import QDialog, QInputDialog
 
 from eric7.EricGui import EricPixmapCache
 from eric7.EricWidgets.EricApplication import ericApp
@@ -720,6 +720,9 @@
         self.bootPicker.setMode(EricPathPickerModes.DIRECTORY_SHOW_FILES_MODE)
         self.bootPicker.setEnabled(False)
 
+        self.searchBootButton.setIcon(EricPixmapCache.getIcon("question"))
+        self.searchBootButton.setEnabled(False)
+
         self.__mandatoryStyleSheet = (
             "QLineEdit {border: 2px solid; border-color: #dd8888}"
             if ericApp().usesDarkPalette()
@@ -1028,6 +1031,7 @@
         vidpid = self.devicesComboBox.itemData(index, self.DeviceVidPidRole)
         boardType = self.devicesComboBox.itemData(index, self.DeviceTypeRole)
 
+        self.searchBootButton.setEnabled(boardType == self.__manualType)
         self.bootPicker.setEnabled(boardType == self.__manualType)
         if boardType == self.__manualType:
             self.__showManualInstructions()
@@ -1071,3 +1075,35 @@
         @type str
         """
         self.__updateFlashButton()
+
+    @pyqtSlot()
+    def on_searchBootButton_clicked(self):
+        """
+        Private slot to look for all known boot paths and present a list to select from.
+        """
+        foundBootVolumes = set()
+        for boardType in SupportedUF2Boards:
+            for volumes in SupportedUF2Boards[boardType]["volumes"].values():
+                for volume in volumes:
+                    foundBootVolumes.update(
+                        FileSystemUtilities.findVolume(volume, findAll=True)
+                    )
+
+        if len(foundBootVolumes) == 0:
+            selectedVolume = ""
+        elif len(foundBootVolumes) == 1:
+            selectedVolume = list(foundBootVolumes)[0]
+        else:
+            result, ok = QInputDialog.getItem(
+                None,
+                QCoreApplication.translate("UF2FlashDialog", "Flash UF2 Device"),
+                QCoreApplication.translate(
+                    "UF2FlashDialog", "Select the Boot Volume of the device:"
+                ),
+                list(foundBootVolumes),
+                0,
+                True,
+            )
+            selectedVolume = result if ok else ""
+
+        self.bootPicker.setText(selectedVolume)
--- a/src/eric7/MicroPython/UF2FlashDialog.ui	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/MicroPython/UF2FlashDialog.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -26,7 +26,7 @@
        </property>
       </widget>
      </item>
-     <item row="0" column="1">
+     <item row="0" column="1" colspan="2">
       <widget class="QComboBox" name="devicesComboBox">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@@ -46,7 +46,7 @@
        </property>
       </widget>
      </item>
-     <item row="1" column="1">
+     <item row="1" column="1" colspan="2">
       <widget class="EricPathPicker" name="firmwarePicker" native="true">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@@ -65,7 +65,7 @@
      <item row="2" column="0">
       <widget class="QLabel" name="label_2">
        <property name="text">
-        <string>'Boot' Path:</string>
+        <string>'Boot' Volume:</string>
        </property>
       </widget>
      </item>
@@ -85,6 +85,13 @@
        </property>
       </widget>
      </item>
+     <item row="2" column="2">
+      <widget class="QToolButton" name="searchBootButton">
+       <property name="toolTip">
+        <string>Press to check for all known boot volume names.</string>
+       </property>
+      </widget>
+     </item>
     </layout>
    </item>
    <item>
@@ -167,6 +174,7 @@
   <tabstop>devicesComboBox</tabstop>
   <tabstop>firmwarePicker</tabstop>
   <tabstop>bootPicker</tabstop>
+  <tabstop>searchBootButton</tabstop>
   <tabstop>flashButton</tabstop>
   <tabstop>infoEdit</tabstop>
   <tabstop>refreshButton</tabstop>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiApConfigDialog.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to configure the Access Point interface.
+"""
+
+from PyQt6.QtCore import pyqtSlot
+from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QLineEdit
+
+from eric7 import Preferences
+from eric7.EricGui import EricPixmapCache
+
+from .Ui_WifiApConfigDialog import Ui_WifiApConfigDialog
+
+
+class WifiApConfigDialog(QDialog, Ui_WifiApConfigDialog):
+    """
+    Class implementing a dialog to configure the Access Point interface.
+    """
+
+    def __init__(self, withIP, parent=None):
+        """
+        Constructor
+
+        @param withIP flag indicating to ask the user for an IP configuration
+        @type bool
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+
+        self.apShowPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword"))
+
+        # populate the WiFi security mode combo box
+        self.apSecurityComboBox.addItem(self.tr("open"), 0)
+        self.apSecurityComboBox.addItem("WEP", 1)
+        self.apSecurityComboBox.addItem("WPA", 2)
+        self.apSecurityComboBox.addItem("WPA2", 3)
+        self.apSecurityComboBox.addItem("WPA/WPA2", 4)
+        self.apSecurityComboBox.addItem("WPA2 (CCMP)", 5)
+        self.apSecurityComboBox.addItem("WPA3", 6)
+        self.apSecurityComboBox.addItem("WPA2/WPA3", 7)
+
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False)
+
+        # populate the WiFi fields with data saved to the preferences
+        self.apSsidEdit.setText(Preferences.getMicroPython("WifiApName"))
+        self.apPasswordEdit.setText(Preferences.getMicroPython("WifiApPassword"))
+        index = self.apSecurityComboBox.findData(
+            Preferences.getMicroPython("WifiApAuthMode")
+        )
+        if index == -1:
+            index = 5  # default it to WPA/WPA2 in case of an issue
+        self.apSecurityComboBox.setCurrentIndex(index)
+
+        self.__withIP = withIP
+
+        self.ipv4GroupBox.setVisible(withIP)
+        if withIP:
+            # populate the IPv4 configuration with data saved to the preferences
+            self.addressEdit.setText(Preferences.getMicroPython("WifiApAddress"))
+            self.netmaskEdit.setText(Preferences.getMicroPython("WifiApNetmask"))
+            self.gatewayEdit.setText(Preferences.getMicroPython("WifiApGateway"))
+            self.dnsEdit.setText(Preferences.getMicroPython("WifiApDNS"))
+
+            # connect the IPv4 fields
+            self.addressEdit.addressChanged.connect(self.__updateOk)
+            self.netmaskEdit.addressChanged.connect(self.__updateOk)
+            self.gatewayEdit.addressChanged.connect(self.__updateOk)
+            self.dnsEdit.addressChanged.connect(self.__updateOk)
+
+        # connect the WiFi fields
+        self.apSsidEdit.textChanged.connect(self.__updateOk)
+        self.apPasswordEdit.textChanged.connect(self.__updateOk)
+        self.apSecurityComboBox.currentIndexChanged.connect(self.__updateOk)
+
+        self.__updateOk()
+
+        msh = self.minimumSizeHint()
+        self.resize(max(self.width(), msh.width()), msh.height())
+
+    @pyqtSlot()
+    def __updateOk(self):
+        """
+        Private method to update the enabled state of the OK button.
+        """
+        enable = bool(self.apSsidEdit.text())
+        if self.apSecurityComboBox.currentData() != 0:
+            # security needs a password
+            enable &= bool(self.apPasswordEdit.text())
+        if self.__withIP:
+            enable &= (
+                self.addressEdit.hasAcceptableInput()
+                and self.netmaskEdit.hasAcceptableInput()
+                and self.gatewayEdit.hasAcceptableInput()
+                and self.dnsEdit.hasAcceptableInput()
+            )
+
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(enable)
+
+    @pyqtSlot(bool)
+    def on_apShowPasswordButton_clicked(self, checked):
+        """
+        Private slot to show or hide the WiFi Access Point password.
+
+        @param checked state of the button
+        @type bool
+        """
+        if checked:
+            self.apPasswordEdit.setEchoMode(QLineEdit.EchoMode.Normal)
+            self.apShowPasswordButton.setIcon(EricPixmapCache.getIcon("hidePassword"))
+            self.apShowPasswordButton.setToolTip(self.tr("Press to hide the password"))
+        else:
+            self.apPasswordEdit.setEchoMode(QLineEdit.EchoMode.Password)
+            self.apShowPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword"))
+            self.apShowPasswordButton.setToolTip(self.tr("Press to show the password"))
+
+    def getApConfig(self):
+        """
+        Public method to get the entered access point configuration data.
+
+        @return tuple containing the SSID, the password, the selected security mode
+            and a flag indicating to save the parameters to the settings
+        @rtype tuple of (str, str, int, bool)
+        """
+        ifconfig = (
+            (
+                self.addressEdit.text(),
+                self.netmaskEdit.text(),
+                self.gatewayEdit.text(),
+                self.dnsEdit.text(),
+            )
+            if self.__withIP
+            else ("", "", "", "")
+        )
+
+        return (
+            self.apSsidEdit.text(),
+            self.apPasswordEdit.text(),
+            self.apSecurityComboBox.currentData(),
+            self.rememberCheckBox.isChecked(),
+            ifconfig,
+        )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiApConfigDialog.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WifiApConfigDialog</class>
+ <widget class="QDialog" name="WifiApConfigDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>315</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Access Point Configuration</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_2">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label_10">
+     <property name="text">
+      <string>Name:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1" colspan="2">
+    <widget class="QLineEdit" name="apSsidEdit">
+     <property name="toolTip">
+      <string>Enter the network name (SSID) to publish</string>
+     </property>
+     <property name="clearButtonEnabled">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_12">
+     <property name="text">
+      <string>Password:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLineEdit" name="apPasswordEdit">
+     <property name="toolTip">
+      <string>Enter the network password</string>
+     </property>
+     <property name="echoMode">
+      <enum>QLineEdit::Password</enum>
+     </property>
+     <property name="clearButtonEnabled">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="2">
+    <widget class="QToolButton" name="apShowPasswordButton">
+     <property name="toolTip">
+      <string>Press to show the password</string>
+     </property>
+     <property name="checkable">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="label_23">
+     <property name="text">
+      <string>Security:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1" colspan="2">
+    <layout class="QHBoxLayout" name="horizontalLayout_6">
+     <item>
+      <widget class="QComboBox" name="apSecurityComboBox">
+       <property name="toolTip">
+        <string>Select the security mode</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_3">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+   <item row="3" column="0" colspan="3">
+    <widget class="QGroupBox" name="ipv4GroupBox">
+     <property name="title">
+      <string>IPv4 Configuration</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <layout class="QGridLayout" name="gridLayout">
+        <item row="0" column="0">
+         <widget class="QLabel" name="label">
+          <property name="text">
+           <string>Address:</string>
+          </property>
+         </widget>
+        </item>
+        <item row="0" column="1">
+         <widget class="EricIPv4InputWidget" name="addressEdit" native="true">
+          <property name="focusPolicy">
+           <enum>Qt::NoFocus</enum>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="0">
+         <widget class="QLabel" name="label_2">
+          <property name="text">
+           <string>Netmask:</string>
+          </property>
+         </widget>
+        </item>
+        <item row="1" column="1">
+         <widget class="EricIPv4InputWidget" name="netmaskEdit" native="true">
+          <property name="focusPolicy">
+           <enum>Qt::NoFocus</enum>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="0">
+         <widget class="QLabel" name="label_3">
+          <property name="text">
+           <string>Gateway:</string>
+          </property>
+         </widget>
+        </item>
+        <item row="2" column="1">
+         <widget class="EricIPv4InputWidget" name="gatewayEdit" native="true">
+          <property name="focusPolicy">
+           <enum>Qt::NoFocus</enum>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="0">
+         <widget class="QLabel" name="label_4">
+          <property name="text">
+           <string>DNS:</string>
+          </property>
+         </widget>
+        </item>
+        <item row="3" column="1">
+         <widget class="EricIPv4InputWidget" name="dnsEdit" native="true">
+          <property name="focusPolicy">
+           <enum>Qt::NoFocus</enum>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <spacer name="horizontalSpacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>273</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="4" column="0" colspan="3">
+    <widget class="QCheckBox" name="rememberCheckBox">
+     <property name="toolTip">
+      <string>Select to remember the entered connection parameters</string>
+     </property>
+     <property name="text">
+      <string>Remember Parameters</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="0" colspan="3">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>EricIPv4InputWidget</class>
+   <extends>QWidget</extends>
+   <header>eric7/EricNetwork/EricIPv4InputWidget.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>apSsidEdit</tabstop>
+  <tabstop>apPasswordEdit</tabstop>
+  <tabstop>apShowPasswordButton</tabstop>
+  <tabstop>apSecurityComboBox</tabstop>
+  <tabstop>addressEdit</tabstop>
+  <tabstop>netmaskEdit</tabstop>
+  <tabstop>gatewayEdit</tabstop>
+  <tabstop>dnsEdit</tabstop>
+  <tabstop>rememberCheckBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>WifiApConfigDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>WifiApConfigDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiApStationsDialog.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog showing the currently connected stations (clients).
+"""
+
+import binascii
+
+from PyQt6.QtCore import Qt
+from PyQt6.QtWidgets import QDialog, QTreeWidgetItem
+
+from .Ui_WifiApStationsDialog import Ui_WifiApStationsDialog
+
+
+class WifiApStationsDialog(QDialog, Ui_WifiApStationsDialog):
+    """
+    Class documentation goes here.
+    """
+
+    def __init__(self, stations, parent=None):
+        """
+        Constructor
+
+        @param stations list of connected stations. Each entry is a tuple containing the
+            station's MAC-Address and the RSSI (if supported and available)
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+
+        rssiFound = False
+
+        for station in stations:
+            mac = binascii.hexlify(station[0], ":").decode("utf-8")
+            if len(station) > 1:
+                rssiFound = True
+                rssi = str(station[1])
+            else:
+                rssi = ""
+            QTreeWidgetItem(self.stationsList, [mac, rssi, ""])
+
+        self.stationsList.sortItems(0, Qt.SortOrder.AscendingOrder)
+        self.stationsList.resizeColumnToContents(0)
+        self.stationsList.resizeColumnToContents(1)
+        self.stationsList.setColumnHidden(1, not rssiFound)
+        self.stationsList.header().setStretchLastSection(True)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiApStationsDialog.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WifiApStationsDialog</class>
+ <widget class="QDialog" name="WifiApStationsDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>511</width>
+    <height>509</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Connected WiFi Clients</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTreeWidget" name="stationsList">
+     <property name="alternatingRowColors">
+      <bool>true</bool>
+     </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::NoSelection</enum>
+     </property>
+     <property name="rootIsDecorated">
+      <bool>false</bool>
+     </property>
+     <property name="itemsExpandable">
+      <bool>false</bool>
+     </property>
+     <property name="sortingEnabled">
+      <bool>true</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string>Name</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>RSSI [dBm]</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Close</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>WifiApStationsDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>WifiApStationsDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiConnectionDialog.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to enter the parameters needed to connect to a WiFi
+network.
+"""
+
+from PyQt6.QtCore import pyqtSlot
+from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QLineEdit
+
+from eric7 import Preferences
+from eric7.EricGui import EricPixmapCache
+
+from .Ui_WifiConnectionDialog import Ui_WifiConnectionDialog
+
+
+class WifiConnectionDialog(QDialog, Ui_WifiConnectionDialog):
+    """
+    Class implementing a dialog to enter the parameters needed to connect to a WiFi
+    network.
+    """
+
+    def __init__(self, parent=None):
+        """
+        Constructor
+
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+
+        self.showPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword"))
+
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False)
+
+        # populate the field with data saved to the preferences
+        self.ssidEdit.setText(Preferences.getMicroPython("WifiName"))
+        self.passwordEdit.setText(Preferences.getMicroPython("WifiPassword"))
+
+        msh = self.minimumSizeHint()
+        self.resize(max(self.width(), msh.width()), msh.height())
+
+    @pyqtSlot(str)
+    def on_ssidEdit_textChanged(self, ssid):
+        """
+        Private slot handling a change of the SSID.
+
+        @param ssid entered SSID
+        @type str
+        """
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(bool(ssid))
+
+    @pyqtSlot(bool)
+    def on_showPasswordButton_clicked(self, checked):
+        """
+        Private slot to show or hide the password.
+
+        @param checked state of the button
+        @type bool
+        """
+        if checked:
+            self.passwordEdit.setEchoMode(QLineEdit.EchoMode.Normal)
+            self.showPasswordButton.setIcon(EricPixmapCache.getIcon("hidePassword"))
+            self.showPasswordButton.setToolTip(self.tr("Press to hide the password"))
+        else:
+            self.passwordEdit.setEchoMode(QLineEdit.EchoMode.Password)
+            self.showPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword"))
+            self.showPasswordButton.setToolTip(self.tr("Press to show the password"))
+
+    def getConnectionParameters(self):
+        """
+        Public method to get the entered connection parameters.
+
+        @return tuple containing the SSID, password and a flag indicating, if the
+            parameters shall be saved to the preferences
+        @rtype tuple of (str, str, bool)
+        """
+        return (
+            self.ssidEdit.text(),
+            self.passwordEdit.text(),
+            self.rememberCheckBox.isChecked(),
+        )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiConnectionDialog.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WifiConnectionDialog</class>
+ <widget class="QDialog" name="WifiConnectionDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>138</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>WiFi Connection Parameters</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Name:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1" colspan="2">
+    <widget class="QLineEdit" name="ssidEdit">
+     <property name="toolTip">
+      <string>Enter the network name (SSID) to connect to</string>
+     </property>
+     <property name="clearButtonEnabled">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Password:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLineEdit" name="passwordEdit">
+     <property name="toolTip">
+      <string>Enter the network password</string>
+     </property>
+     <property name="echoMode">
+      <enum>QLineEdit::Password</enum>
+     </property>
+     <property name="clearButtonEnabled">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="2">
+    <widget class="QToolButton" name="showPasswordButton">
+     <property name="toolTip">
+      <string>Press to show the password</string>
+     </property>
+     <property name="checkable">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="3">
+    <widget class="QCheckBox" name="rememberCheckBox">
+     <property name="toolTip">
+      <string>Select to remember the entered connection parameters</string>
+     </property>
+     <property name="text">
+      <string>Remember Parameters</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" colspan="3">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>ssidEdit</tabstop>
+  <tabstop>passwordEdit</tabstop>
+  <tabstop>showPasswordButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>WifiConnectionDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>WifiConnectionDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiController.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,386 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the WiFi related functionality.
+"""
+
+from PyQt6.QtCore import QObject, pyqtSlot
+from PyQt6.QtWidgets import QDialog, QMenu
+
+from eric7 import Preferences
+from eric7.EricGui.EricOverrideCursor import EricOverrideCursor
+from eric7.EricWidgets import EricMessageBox
+
+
+class WifiController(QObject):
+    """
+    Class implementing the WiFi related functionality.
+    """
+
+    def __init__(self, microPython, parent=None):
+        """
+        Constructor
+
+        @param microPython reference to the MicroPython widget
+        @type MicroPythonWidgep
+        @param parent reference to the parent object (defaults to None)
+        @type QObject (optional)
+        """
+        super().__init__(parent)
+
+        self.__mpy = microPython
+
+    def createMenu(self, menu):
+        """
+        Public method to create the WiFi submenu.
+
+        @param menu reference to the parent menu
+        @type QMenu
+        @return reference to the created menu
+        @rtype QMenu
+        """
+        wifiMenu = QMenu(self.tr("WiFi Functions"), menu)
+        wifiMenu.setTearOffEnabled(True)
+        wifiMenu.addAction(self.tr("Show WiFi Status"), self.__showWifiStatus)
+        wifiMenu.addSeparator()
+        wifiMenu.addAction(self.tr("Connect WiFi"), self.__connectWifi)
+        wifiMenu.addAction(self.tr("Check Internet Connection"), self.__checkInternet)
+        wifiMenu.addAction(self.tr("Disconnect WiFi"), self.__disconnectWifi)
+        wifiMenu.addSeparator()
+        wifiMenu.addAction(self.tr("Scan Networks"), self.__scanNetwork)
+        wifiMenu.addSeparator()
+        wifiMenu.addAction(self.tr("Write WiFi Credentials"), self.__writeCredentials)
+        wifiMenu.addAction(self.tr("Remove WiFi Credentials"), self.__removeCredentials)
+        wifiMenu.addSeparator()
+        wifiMenu.addAction(self.tr("Start WiFi Access Point"), self.__startAccessPoint)
+        wifiMenu.addAction(
+            self.tr("Start WiFi Access Point with IP"), self.__startAccessPointIP
+        )
+        wifiMenu.addAction(
+            self.tr("Show Connected Clients"), self.__showConnectedClients
+        )
+        wifiMenu.addAction(self.tr("Stop WiFi Access Point"), self.__stopAccessPoint)
+        wifiMenu.addSeparator()
+        wifiMenu.addAction(
+            self.tr("Deactivate Client Interface"),
+            lambda: self.__deactivateInterface("STA"),
+        )
+        wifiMenu.addAction(
+            self.tr("Deactivate Access Point Interface"),
+            lambda: self.__deactivateInterface("AP"),
+        )
+
+        # add device specific entries (if there are any)
+        self.__mpy.getDevice().addDeviceWifiEntries(wifiMenu)
+
+        return wifiMenu
+
+    @pyqtSlot()
+    def __showWifiStatus(self):
+        """
+        Private slot to show a dialog with the WiFi status of the current device.
+        """
+        from .WifiStatusDialog import WifiStatusDialog
+
+        try:
+            clientStatus, apStatus, overallStatus = self.__mpy.getDevice().getWifiData()
+
+            dlg = WifiStatusDialog(clientStatus, apStatus, overallStatus)
+            dlg.exec()
+        except Exception as exc:
+            self.__mpy.showError("getWifiData()", str(exc))
+
+    @pyqtSlot()
+    def __connectWifi(self):
+        """
+        Private slot to connect the current device to a WiFi network.
+        """
+        from .WifiConnectionDialog import WifiConnectionDialog
+
+        dlg = WifiConnectionDialog()
+        if dlg.exec() == QDialog.DialogCode.Accepted:
+            ssid, password, remember = dlg.getConnectionParameters()
+            if remember:
+                # save the parameters to the preferences
+                Preferences.setMicroPython("WifiName", ssid)
+                Preferences.setMicroPython("WifiPassword", password)
+            success, error = self.__mpy.getDevice().connectWifi(ssid, password)
+            if success:
+                EricMessageBox.information(
+                    None,
+                    self.tr("Connect WiFi"),
+                    self.tr(
+                        "<p>The device was connected to <b>{0}</b> successfully.</p>"
+                    ).format(ssid),
+                )
+            else:
+                EricMessageBox.critical(
+                    None,
+                    self.tr("Connect WiFi"),
+                    self.tr(
+                        "<p>The device could not connect to <b>{0}</b>.</p>"
+                        "<p>Reason: {1}</p>"
+                    ).format(ssid, error if error else self.tr("unknown")),
+                )
+
+    @pyqtSlot()
+    def __disconnectWifi(self):
+        """
+        Private slot to disconnect the current device from the WiFi network.
+        """
+        success, error = self.__mpy.getDevice().disconnectWifi()
+        if success:
+            EricMessageBox.information(
+                None,
+                self.tr("Disconnect WiFi"),
+                self.tr("<p>The device was disconnected from the WiFi network.</p>"),
+            )
+        else:
+            EricMessageBox.critical(
+                None,
+                self.tr("Disconnect WiFi"),
+                self.tr(
+                    "<p>The device could not be disconnected.</p><p>Reason: {0}</p>"
+                ).format(error if error else self.tr("unknown")),
+            )
+
+    @pyqtSlot()
+    def __checkInternet(self):
+        """
+        Private slot to check the availability of an internet connection.
+        """
+        success, error = self.__mpy.getDevice().checkInternet()
+        if not error:
+            msg = (
+                self.tr("<p>The internet connection is <b>available</b>.</p>")
+                if success
+                else self.tr("<p>The internet connection is <b>not available</b>.</p>")
+            )
+            EricMessageBox.information(
+                None,
+                self.tr("Check Internet Connection"),
+                msg,
+            )
+        else:
+            EricMessageBox.critical(
+                None,
+                self.tr("Check Internet Connection"),
+                self.tr(
+                    "<p>The internet is not available.</p><p>Reason: {0}</p>"
+                ).format(error if error else self.tr("unknown")),
+            )
+
+    @pyqtSlot()
+    def __scanNetwork(self):
+        """
+        Private slot to scan for visible WiFi networks.
+        """
+        from .WifiNetworksWindow import WifiNetworksWindow
+
+        win = WifiNetworksWindow(self.__mpy.getDevice(), self.__mpy)
+        win.show()
+        win.scanNetworks()
+
+    @pyqtSlot()
+    def __writeCredentials(self):
+        """
+        Private slot to save the WiFi login credentials to the connected device.
+
+        This will also modify the boot script to perform an automatic WiFi connection.
+        """
+        from .WifiConnectionDialog import WifiConnectionDialog
+
+        dlg = WifiConnectionDialog()
+        if dlg.exec() == QDialog.DialogCode.Accepted:
+            ssid, password, remember = dlg.getConnectionParameters()
+            if remember:
+                # save the parameters to the preferences
+                Preferences.setMicroPython("WifiName", ssid)
+                Preferences.setMicroPython("WifiPassword", password)
+            success, error = self.__mpy.getDevice().writeCredentials(ssid, password)
+            if success:
+                EricMessageBox.information(
+                    None,
+                    self.tr("Write WiFi Credentials"),
+                    self.tr(
+                        "<p>The WiFi credentials were saved on the device. The device"
+                        " will connect to the WiFi network at boot time.</p>"
+                    ),
+                )
+            else:
+                EricMessageBox.critical(
+                    None,
+                    self.tr("Write WiFi Credentials"),
+                    self.tr(
+                        "<p>The WiFi credentials could not be saved on the device.</p>"
+                        "<p>Reason: {0}</p>"
+                    ).format(error if error else self.tr("unknown")),
+                )
+
+    @pyqtSlot()
+    def __removeCredentials(self):
+        """
+        Private slot to remove the saved WiFi credentials from the connected device.
+
+        This will not remove the auto-connect part of the boot script. This needs to be
+        done manually if desired.
+        """
+        ok = EricMessageBox.yesNo(
+            None,
+            self.tr("Remove WiFi Credentials"),
+            self.tr(
+                "Shall the saved WiFi credentials really be removed from the connected"
+                " device?"
+            ),
+        )
+        if ok:
+            success, error = self.__mpy.getDevice().removeCredentials()
+            if success:
+                EricMessageBox.information(
+                    None,
+                    self.tr("Remove WiFi Credentials"),
+                    self.tr(
+                        "<p>The WiFi credentials were removed from the device. The"
+                        " device will not connect to the WiFi network at boot time"
+                        " anymore.</p>"
+                    ),
+                )
+            else:
+                EricMessageBox.critical(
+                    None,
+                    self.tr("Remove WiFi Credentials"),
+                    self.tr(
+                        "<p>The WiFi credentials could not be removed from the device."
+                        "</p><p>Reason: {0}</p>"
+                    ).format(error if error else self.tr("unknown")),
+                )
+
+    @pyqtSlot()
+    def __startAccessPoint(self, withIP=False):
+        """
+        Private slot to start the Access Point interface of the connected device.
+
+        @param withIP flag indicating to start the access point with an IP configuration
+        @type bool
+        """
+        from .WifiApConfigDialog import WifiApConfigDialog
+
+        dlg = WifiApConfigDialog(withIP=withIP)
+        if dlg.exec() == QDialog.DialogCode.Accepted:
+            ssid, password, security, remember, ifconfig = dlg.getApConfig()
+
+            if remember:
+                Preferences.setMicroPython("WifiApName", ssid)
+                Preferences.setMicroPython("WifiApPassword", password)
+                Preferences.setMicroPython("WifiApAuthMode", security)
+                if withIP:
+                    Preferences.setMicroPython("WifiApAddress", ifconfig[0])
+                    Preferences.setMicroPython("WifiApNetmask", ifconfig[1])
+                    Preferences.setMicroPython("WifiApGateway", ifconfig[2])
+                    Preferences.setMicroPython("WifiApDNS", ifconfig[3])
+
+            ok, err = self.__mpy.getDevice().startAccessPoint(
+                ssid,
+                security=security,
+                password=password,
+                ifconfig=ifconfig if withIP else None,
+            )
+            if ok:
+                EricMessageBox.information(
+                    None,
+                    self.tr("Start WiFi Access Point"),
+                    self.tr(
+                        "The WiFi Access Point interface was started successfully."
+                    ),
+                )
+            else:
+                msg = self.tr("<p>The WiFi Access Point could not be started.</p>")
+                if err:
+                    msg += self.tr("<p>Reason: {0}").format(err)
+                EricMessageBox.critical(
+                    None,
+                    self.tr("Start WiFi Access Point"),
+                    msg,
+                )
+
+    @pyqtSlot()
+    def __startAccessPointIP(self):
+        """
+        Private slot to start the Access Point interface of the connected device
+        with given IP parameters.
+        """
+        self.__startAccessPoint(withIP=True)
+
+    @pyqtSlot()
+    def __stopAccessPoint(self):
+        """
+        Private slot to stop the Access Point interface of the connected device.
+        """
+        ok, err = self.__mpy.getDevice().stopAccessPoint()
+        if ok:
+            EricMessageBox.information(
+                None,
+                self.tr("Stop WiFi Access Point"),
+                self.tr("The WiFi Access Point interface was stopped successfully."),
+            )
+        else:
+            msg = self.tr("<p>The WiFi Access Point could not be stopped.</p>")
+            if err:
+                msg += self.tr("<p>Reason: {0}").format(err)
+            EricMessageBox.critical(
+                None,
+                self.tr("Stop WiFi Access Point"),
+                msg,
+            )
+
+    @pyqtSlot()
+    def __showConnectedClients(self):
+        """
+        Private slot to show a list of WiFi clients connected to the Access Point
+        interface.
+        """
+        from .WifiApStationsDialog import WifiApStationsDialog
+
+        with EricOverrideCursor():
+            stations, err = self.__mpy.getDevice().getConnectedClients()
+
+        if err:
+            self.__mpy.showError("getConnectedClients()", err)
+        else:
+            if stations:
+                dlg = WifiApStationsDialog(stations)
+                dlg.exec()
+            else:
+                EricMessageBox.information(
+                    None,
+                    self.tr("Show Connected Clients"),
+                    self.tr("No clients are connected to the access point."),
+                )
+
+    def __deactivateInterface(self, interface):
+        """
+        Private method to deactivate a given WiFi interface of the connected device.
+
+        @param interface designation of the interface to be deactivated (one of 'AP'
+            or 'STA')
+        @type str
+        """
+        ok, err = self.__mpy.getDevice().deactivateInterface(interface)
+        if ok:
+            EricMessageBox.information(
+                None,
+                self.tr("Deactivate WiFi Interface"),
+                self.tr("The WiFi interface was deactivated successfully."),
+            )
+        else:
+            msg = self.tr("<p>The WiFi interface could not be deactivated.</p>")
+            if err:
+                msg += self.tr("<p>Reason: {0}").format(err)
+            EricMessageBox.critical(
+                None,
+                self.tr("Deactivate WiFi Interface"),
+                msg,
+            )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiCountryDialog.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+
+"""
+Module implementing a dialog to enter the country code for the WiFi interface.
+"""
+
+from PyQt6.QtCore import pyqtSlot
+from PyQt6.QtWidgets import QDialog, QDialogButtonBox
+
+from eric7 import Preferences
+
+from .Ui_WifiCountryDialog import Ui_WifiCountryDialog
+
+
+class WifiCountryDialog(QDialog, Ui_WifiCountryDialog):
+    """
+    Class implementing a dialog to enter the country code for the WiFi interface.
+    """
+
+    def __init__(self, parent=None):
+        """
+        Constructor
+
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False)
+
+        self.countryEdit.setText(Preferences.getMicroPython("WifiCountry").upper())
+
+        msh = self.minimumSizeHint()
+        self.resize(max(self.width(), msh.width()), msh.height())
+
+    @pyqtSlot(str)
+    def on_countryEdit_textChanged(self, country):
+        """
+        Private slot handling a change of the country.
+
+        @param country entered country code
+        @type str
+        """
+        self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(
+            bool(country)
+        )
+
+    def getCountry(self):
+        """
+        Public method to get the entered country code.
+
+        @return tuple containing the country code and a flag indicating to save it to
+            the settings
+        @rtype tuple of (str, bool)
+        """
+        return self.countryEdit.text().upper(), self.rememberCheckBox.isChecked()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiCountryDialog.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WifiCountryDialog</class>
+ <widget class="QDialog" name="WifiCountryDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>250</width>
+    <height>106</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>WiFi Country Code</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label_13">
+     <property name="text">
+      <string>Country:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QLineEdit" name="countryEdit">
+     <property name="toolTip">
+      <string>Enter the country code for the WiFi interface</string>
+     </property>
+     <property name="maxLength">
+      <number>3</number>
+     </property>
+     <property name="clearButtonEnabled">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="3">
+    <widget class="QCheckBox" name="rememberCheckBox">
+     <property name="toolTip">
+      <string>Select to remember the entered connection parameters</string>
+     </property>
+     <property name="text">
+      <string>Remember Parameters</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="3">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>countryEdit</tabstop>
+  <tabstop>rememberCheckBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>WifiCountryDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>WifiCountryDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiNetworksWindow.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,154 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog showing the available WiFi networks.
+"""
+
+from PyQt6.QtCore import Qt, QTimer, pyqtSlot
+from PyQt6.QtWidgets import QHeaderView, QTreeWidgetItem, QWidget
+
+from eric7.EricGui.EricOverrideCursor import EricOverrideCursor
+from eric7.EricWidgets import EricMessageBox
+
+from .Ui_WifiNetworksWindow import Ui_WifiNetworksWindow
+
+
+class WifiNetworksWindow(QWidget, Ui_WifiNetworksWindow):
+    """
+    Class implementing a dialog showing the available WiFi networks.
+    """
+
+    def __init__(self, device, parent=None):
+        """
+        Constructor
+
+        @param device reference to the connected device
+        @type BaseDevice
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+
+        windowFlags = self.windowFlags()
+        windowFlags |= Qt.WindowType.Window
+        windowFlags |= Qt.WindowType.WindowContextHelpButtonHint
+        self.setWindowFlags(windowFlags)
+
+        self.__device = device
+
+        self.__scanTimer = QTimer(self)
+        self.__scanTimer.timeout.connect(self.scanNetworks)
+
+        self.scanButton.clicked.connect(self.scanNetworks)
+
+        self.networkList.sortByColumn(0, Qt.SortOrder.AscendingOrder)
+
+    def scanNetworks(self):
+        """
+        Public method to ask the device for a network scan and display the result.
+        """
+        self.networkList.clear()
+        self.statusLabel.clear()
+
+        if not self.periodicCheckBox.isChecked():
+            self.scanButton.setEnabled(False)
+        with EricOverrideCursor():
+            networks, error = self.__device.scanNetworks()
+        if not self.periodicCheckBox.isChecked():
+            self.scanButton.setEnabled(True)
+
+        if error:
+            EricMessageBox.warning(
+                self,
+                self.tr("Scan WiFi Networks"),
+                self.tr(
+                    """<p>The scan for available WiFi networks failed.</p>"""
+                    """<p>Reason: {0}</p>"""
+                ).format(error),
+            )
+            if self.periodicCheckBox.isChecked():
+                self.periodicCheckBox.setChecked(False)
+
+        else:
+            self.statusLabel.setText(
+                self.tr("<p>Detected <b>%n</b> network(s).</p>", "", len(networks))
+            )
+            macSeen = False
+            for network in networks:
+                if network[1]:
+                    macSeen = True
+                itm = QTreeWidgetItem(
+                    self.networkList,
+                    [
+                        network[0],
+                        str(network[2]),
+                        network[1],
+                        str(network[3]),
+                        network[4],
+                    ],
+                )
+                itm.setTextAlignment(1, Qt.AlignmentFlag.AlignHCenter)
+                itm.setTextAlignment(2, Qt.AlignmentFlag.AlignHCenter)
+                itm.setTextAlignment(3, Qt.AlignmentFlag.AlignHCenter)
+                itm.setTextAlignment(4, Qt.AlignmentFlag.AlignHCenter)
+
+            self.networkList.setColumnHidden(2, not macSeen)
+            self.__resizeColumns()
+            self.__resort()
+
+    def __resort(self):
+        """
+        Private method to resort the networks list.
+        """
+        self.networkList.sortItems(
+            self.networkList.sortColumn(),
+            self.networkList.header().sortIndicatorOrder(),
+        )
+
+    def __resizeColumns(self):
+        """
+        Private method to resize the columns of the result list.
+        """
+        self.networkList.header().resizeSections(
+            QHeaderView.ResizeMode.ResizeToContents
+        )
+        self.networkList.header().setStretchLastSection(True)
+
+    def closeEvent(self, evt):
+        """
+        Protected method to handle a window close event.
+
+        @param evt reference to the close event
+        @type QCloseEvent
+        """
+        self.__scanTimer.stop()
+
+    @pyqtSlot(bool)
+    def on_periodicCheckBox_toggled(self, checked):
+        """
+        Private slot handling the selection of a periodic scan.
+
+        @param checked flag indicating a periodic scan
+        @type bool
+        """
+        self.scanButton.setEnabled(not checked)
+        if checked:
+            self.__scanTimer.setInterval(self.intervalSpinBox.value() * 1000)
+            self.__scanTimer.start()
+        else:
+            self.__scanTimer.stop()
+
+    @pyqtSlot(int)
+    def on_intervalSpinBox_valueChanged(self, interval):
+        """
+        Private slot handling a change of the periodic scan interval.
+
+        @param interval periodic scan interval
+        @type int
+        """
+        if self.periodicCheckBox.isChecked():
+            self.__scanTimer.setInterval(interval * 1000)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiNetworksWindow.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WifiNetworksWindow</class>
+ <widget class="QWidget" name="WifiNetworksWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>650</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>WiFi Networks</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTreeWidget" name="networkList">
+     <property name="alternatingRowColors">
+      <bool>true</bool>
+     </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::NoSelection</enum>
+     </property>
+     <property name="rootIsDecorated">
+      <bool>false</bool>
+     </property>
+     <property name="itemsExpandable">
+      <bool>false</bool>
+     </property>
+     <property name="sortingEnabled">
+      <bool>true</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string>Name</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Channel</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>MAC-Address</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>RSSI [dBm]</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Security</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="statusLabel"/>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QPushButton" name="scanButton">
+       <property name="toolTip">
+        <string>Press to scan for available WiFi networks.</string>
+       </property>
+       <property name="text">
+        <string>Scan</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="text">
+        <string>Scan Interval:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QSpinBox" name="intervalSpinBox">
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+       <property name="suffix">
+        <string> s</string>
+       </property>
+       <property name="minimum">
+        <number>5</number>
+       </property>
+       <property name="maximum">
+        <number>120</number>
+       </property>
+       <property name="value">
+        <number>15</number>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QCheckBox" name="periodicCheckBox">
+       <property name="text">
+        <string>Periodic Scan</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Close</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>networkList</tabstop>
+  <tabstop>scanButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>WifiNetworksWindow</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>269</x>
+     <y>563</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>271</x>
+     <y>517</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiStatusDialog.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,222 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to show the WiFi status of the connected device.
+"""
+
+import contextlib
+
+from PyQt6.QtWidgets import QDialog, QTreeWidgetItem
+
+from .Ui_WifiStatusDialog import Ui_WifiStatusDialog
+
+
+class WifiStatusDialog(QDialog, Ui_WifiStatusDialog):
+    """
+    Class implementing a dialog to show the WiFi status of the connected device.
+    """
+
+    def __init__(self, clientStatus, apStatus, overallStatus, parent=None):
+        """
+        Constructor
+
+        @param clientStatus dictionary containing the WiFi status data of the
+            client interface
+        @type dict
+        @param apStatus dictionary containing the WiFi status data of the
+            access point interface
+        @type dict
+        @param overallStatus dictionary containing the overall WiFi status data
+        @type dict
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+
+        self.statusTree.setColumnCount(2)
+
+        # overall status
+        QTreeWidgetItem(
+            self.statusTree,
+            [
+                self.tr("Active"),
+                self.tr("Yes") if overallStatus["active"] else self.tr("No"),
+            ],
+        )
+
+        # client interface
+        if clientStatus:
+            header = self.__createHeader(self.tr("Client"))
+            QTreeWidgetItem(
+                header,
+                [
+                    self.tr("Active"),
+                    self.tr("Yes") if clientStatus["active"] else self.tr("No"),
+                ],
+            )
+            if clientStatus["active"]:
+                QTreeWidgetItem(
+                    header,
+                    [
+                        self.tr("Connected"),
+                        self.tr("Yes") if clientStatus["connected"] else self.tr("No"),
+                    ],
+                )
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(header, [self.tr("Status"), clientStatus["status"]])
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(
+                        header, [self.tr("Hostname"), clientStatus["hostname"]]
+                    )
+                QTreeWidgetItem(
+                    header, [self.tr("IPv4 Address"), clientStatus["ifconfig"][0]]
+                )
+                QTreeWidgetItem(
+                    header, [self.tr("Netmask"), clientStatus["ifconfig"][1]]
+                )
+                QTreeWidgetItem(
+                    header, [self.tr("Gateway"), clientStatus["ifconfig"][2]]
+                )
+                QTreeWidgetItem(header, [self.tr("DNS"), clientStatus["ifconfig"][3]])
+                QTreeWidgetItem(header, [self.tr("MAC-Address"), clientStatus["mac"]])
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(
+                        header, [self.tr("Channel"), str(clientStatus["channel"])]
+                    )
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(
+                        header, [self.tr("Country"), clientStatus["country"]]
+                    )
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(
+                        header,
+                        [
+                            self.tr("Tx-Power"),
+                            self.tr("{0} dBm").format(clientStatus["txpower"]),
+                        ],
+                    )
+
+                if "ap_ssid" in clientStatus:
+                    apHeader = self.__createSubheader(
+                        header, self.tr("Connected Access Point")
+                    )
+                    QTreeWidgetItem(
+                        apHeader, [self.tr("Name"), clientStatus["ap_ssid"]]
+                    )
+                    with contextlib.suppress(KeyError):
+                        QTreeWidgetItem(
+                            apHeader,
+                            [self.tr("Channel"), str(clientStatus["ap_channel"])],
+                        )
+                    QTreeWidgetItem(
+                        apHeader, [self.tr("MAC-Address"), clientStatus["ap_bssid"]]
+                    )
+                    QTreeWidgetItem(
+                        apHeader, [self.tr("RSSI [dBm]"), str(clientStatus["ap_rssi"])]
+                    )
+                    QTreeWidgetItem(
+                        apHeader, [self.tr("Security"), clientStatus["ap_security"]]
+                    )
+                    with contextlib.suppress(KeyError):
+                        QTreeWidgetItem(
+                            apHeader, [self.tr("Country"), clientStatus["ap_country"]]
+                        )
+
+        # access point interface
+        if apStatus:
+            header = self.__createHeader(self.tr("Access Point"))
+            QTreeWidgetItem(
+                header,
+                [
+                    self.tr("Active"),
+                    self.tr("Yes") if apStatus["active"] else self.tr("No"),
+                ],
+            )
+            if apStatus["active"]:
+                QTreeWidgetItem(
+                    header,
+                    [
+                        self.tr("Connected"),
+                        self.tr("Yes") if apStatus["connected"] else self.tr("No"),
+                    ],
+                )
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(header, [self.tr("Status"), apStatus["status"]])
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(header, [self.tr("Hostname"), apStatus["hostname"]])
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(
+                        header, [self.tr("IPv4 Address"), apStatus["ifconfig"][0]]
+                    )
+                    QTreeWidgetItem(
+                        header, [self.tr("Netmask"), apStatus["ifconfig"][1]]
+                    )
+                    QTreeWidgetItem(
+                        header, [self.tr("Gateway"), apStatus["ifconfig"][2]]
+                    )
+                    QTreeWidgetItem(header, [self.tr("DNS"), apStatus["ifconfig"][3]])
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(header, [self.tr("SSID"), apStatus["essid"]])
+                QTreeWidgetItem(header, [self.tr("MAC-Address"), apStatus["mac"]])
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(
+                        header, [self.tr("Channel"), str(apStatus["channel"])]
+                    )
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(header, [self.tr("Country"), apStatus["country"]])
+                with contextlib.suppress(KeyError):
+                    QTreeWidgetItem(
+                        header,
+                        [
+                            self.tr("Tx-Power"),
+                            self.tr("{0} dBm").format(apStatus["txpower"]),
+                        ],
+                    )
+
+        for col in range(self.statusTree.columnCount()):
+            self.statusTree.resizeColumnToContents(col)
+
+    def __createHeader(self, headerText):
+        """
+        Private method to create a header item.
+
+        @param headerText text for the header item
+        @type str
+        @return reference to the created header item
+        @rtype QTreeWidgetItem
+        """
+        headerItem = QTreeWidgetItem(self.statusTree, [headerText])
+        headerItem.setExpanded(True)
+        headerItem.setFirstColumnSpanned(True)
+
+        font = headerItem.font(0)
+        font.setBold(True)
+
+        headerItem.setFont(0, font)
+
+        return headerItem
+
+    def __createSubheader(self, parent, text):
+        """
+        Private method to create a subheader item.
+
+        @param parent reference to the parent item
+        @type QTreeWidgetItem
+        @param text text for the header item
+        @type str
+        @return reference to the created header item
+        @rtype QTreeWidgetItem
+        """
+        headerItem = QTreeWidgetItem(parent, [text])
+        headerItem.setExpanded(True)
+        headerItem.setFirstColumnSpanned(True)
+
+        font = headerItem.font(0)
+        font.setUnderline(True)
+        headerItem.setFont(0, font)
+
+        return headerItem
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/WifiStatusDialog.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WifiStatusDialog</class>
+ <widget class="QDialog" name="WifiStatusDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>600</width>
+    <height>650</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>WiFi Status</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="font">
+      <font>
+       <pointsize>14</pointsize>
+       <bold>true</bold>
+      </font>
+     </property>
+     <property name="text">
+      <string>WiFi Status</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QTreeWidget" name="statusTree">
+     <property name="headerHidden">
+      <bool>true</bool>
+     </property>
+     <column>
+      <property name="text">
+       <string notr="true">1</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>WifiStatusDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>WifiStatusDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/WifiDialogs/__init__.py	Fri Mar 03 11:31:53 2023 +0100
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Package implementing WiFi related dialogs.
+"""
--- a/src/eric7/Preferences/ConfigurationPages/MicroPythonPage.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Preferences/ConfigurationPages/MicroPythonPage.py	Fri Mar 03 11:31:53 2023 +0100
@@ -7,8 +7,11 @@
 Module implementing the MicroPython configuration page.
 """
 
+from PyQt6.QtCore import pyqtSlot
+from PyQt6.QtWidgets import QLineEdit
 
 from eric7 import Preferences
+from eric7.EricGui import EricPixmapCache
 from eric7.EricWidgets.EricPathPicker import EricPathPickerModes
 from eric7.MicroPython.MicroPythonWidget import AnsiColorSchemes
 from eric7.SystemUtilities import FileSystemUtilities, OSUtilities
@@ -38,6 +41,9 @@
         self.setupUi(self)
         self.setObjectName("MicroPythonPage")
 
+        self.showPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword"))
+        self.apShowPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword"))
+
         self.workspacePicker.setMode(EricPathPickerModes.DIRECTORY_MODE)
 
         self.colorSchemeComboBox.addItems(sorted(AnsiColorSchemes.keys()))
@@ -78,6 +84,16 @@
         self.dfuUtilPathPicker.setMode(EricPathPickerModes.OPEN_FILE_MODE)
         self.dfuUtilPathPicker.setFilters(self.tr("All Files (*)"))
 
+        # populate the WiFi security mode combo box
+        self.apSecurityComboBox.addItem(self.tr("open"), 0)
+        self.apSecurityComboBox.addItem("WEP", 1)
+        self.apSecurityComboBox.addItem("WPA", 2)
+        self.apSecurityComboBox.addItem("WPA2", 3)
+        self.apSecurityComboBox.addItem("WPA/WPA2", 4)
+        self.apSecurityComboBox.addItem("WPA2 (CCMP)", 5)
+        self.apSecurityComboBox.addItem("WPA3", 6)
+        self.apSecurityComboBox.addItem("WPA2/WPA3", 7)
+
         # set initial values
         # workspace
         self.workspacePicker.setText(
@@ -114,6 +130,23 @@
             index = 0
         self.chartThemeComboBox.setCurrentIndex(index)
 
+        # WiFi
+        self.countryEdit.setText(Preferences.getMicroPython("WifiCountry").upper())
+        self.ssidEdit.setText(Preferences.getMicroPython("WifiName"))
+        self.passwordEdit.setText(Preferences.getMicroPython("WifiPassword"))
+        self.apSsidEdit.setText(Preferences.getMicroPython("WifiApName"))
+        self.apPasswordEdit.setText(Preferences.getMicroPython("WifiApPassword"))
+        index = self.apSecurityComboBox.findData(
+            Preferences.getMicroPython("WifiApAuthMode")
+        )
+        if index == -1:
+            index = 5  # default it to WPA/WPA2 in case of an issue
+        self.apSecurityComboBox.setCurrentIndex(index)
+        self.apAddressEdit.setText(Preferences.getMicroPython("WifiApAddress"))
+        self.apNetmaskEdit.setText(Preferences.getMicroPython("WifiApNetmask"))
+        self.apGatewayEdit.setText(Preferences.getMicroPython("WifiApGateway"))
+        self.apDnsEdit.setText(Preferences.getMicroPython("WifiApDNS"))
+
         # MPY Cross Compiler
         self.mpyCrossPicker.setText(Preferences.getMicroPython("MpyCrossCompiler"))
 
@@ -194,6 +227,20 @@
             "ChartColorTheme", self.chartThemeComboBox.currentData()
         )
 
+        # WiFi
+        Preferences.setMicroPython("WifiCountry", self.countryEdit.text().upper())
+        Preferences.setMicroPython("WifiName", self.ssidEdit.text())
+        Preferences.setMicroPython("WifiPassword", self.passwordEdit.text())
+        Preferences.setMicroPython("WifiApName", self.apSsidEdit.text())
+        Preferences.setMicroPython("WifiApPassword", self.apPasswordEdit.text())
+        Preferences.setMicroPython(
+            "WifiApAuthMode", self.apSecurityComboBox.currentData()
+        )
+        Preferences.setMicroPython("WifiApAddress", self.apAddressEdit.text())
+        Preferences.setMicroPython("WifiApNetmask", self.apNetmaskEdit.text())
+        Preferences.setMicroPython("WifiApGateway", self.apGatewayEdit.text())
+        Preferences.setMicroPython("WifiApDNS", self.apDnsEdit.text())
+
         # MPY Cross Compiler
         Preferences.setMicroPython("MpyCrossCompiler", self.mpyCrossPicker.text())
 
@@ -244,6 +291,40 @@
             "CalliopeDocuUrl", self.calliopeDocuUrlLineEdit.text()
         )
 
+    @pyqtSlot(bool)
+    def on_showPasswordButton_clicked(self, checked):
+        """
+        Private slot to show or hide the WiFi client password.
+
+        @param checked state of the button
+        @type bool
+        """
+        if checked:
+            self.passwordEdit.setEchoMode(QLineEdit.EchoMode.Normal)
+            self.showPasswordButton.setIcon(EricPixmapCache.getIcon("hidePassword"))
+            self.showPasswordButton.setToolTip(self.tr("Press to hide the password"))
+        else:
+            self.passwordEdit.setEchoMode(QLineEdit.EchoMode.Password)
+            self.showPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword"))
+            self.showPasswordButton.setToolTip(self.tr("Press to show the password"))
+
+    @pyqtSlot(bool)
+    def on_apShowPasswordButton_clicked(self, checked):
+        """
+        Private slot to show or hide the WiFi Access Point password.
+
+        @param checked state of the button
+        @type bool
+        """
+        if checked:
+            self.apPasswordEdit.setEchoMode(QLineEdit.EchoMode.Normal)
+            self.apShowPasswordButton.setIcon(EricPixmapCache.getIcon("hidePassword"))
+            self.apShowPasswordButton.setToolTip(self.tr("Press to hide the password"))
+        else:
+            self.apPasswordEdit.setEchoMode(QLineEdit.EchoMode.Password)
+            self.apShowPasswordButton.setIcon(EricPixmapCache.getIcon("showPassword"))
+            self.apShowPasswordButton.setToolTip(self.tr("Press to show the password"))
+
 
 def create(dlg):
     """
--- a/src/eric7/Preferences/ConfigurationPages/MicroPythonPage.ui	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Preferences/ConfigurationPages/MicroPythonPage.ui	Fri Mar 03 11:31:53 2023 +0100
@@ -7,10 +7,10 @@
     <x>0</x>
     <y>0</y>
     <width>541</width>
-    <height>1293</height>
+    <height>1847</height>
    </rect>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout_2">
+  <layout class="QVBoxLayout" name="verticalLayout_3">
    <item>
     <widget class="QLabel" name="headerLabel">
      <property name="text">
@@ -208,6 +208,286 @@
     </widget>
    </item>
    <item>
+    <widget class="QGroupBox" name="groupBox_13">
+     <property name="title">
+      <string>WiFi</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_5">
+        <item>
+         <widget class="QLabel" name="label_13">
+          <property name="text">
+           <string>Country:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="countryEdit">
+          <property name="sizePolicy">
+           <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+            <horstretch>0</horstretch>
+            <verstretch>0</verstretch>
+           </sizepolicy>
+          </property>
+          <property name="toolTip">
+           <string>Enter the country code for the WiFi interface</string>
+          </property>
+          <property name="maxLength">
+           <number>3</number>
+          </property>
+          <property name="clearButtonEnabled">
+           <bool>true</bool>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_2">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="groupBox_14">
+        <property name="title">
+         <string>Client</string>
+        </property>
+        <layout class="QGridLayout" name="gridLayout_8">
+         <item row="0" column="0">
+          <widget class="QLabel" name="label_8">
+           <property name="text">
+            <string>Name:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1" colspan="2">
+          <widget class="QLineEdit" name="ssidEdit">
+           <property name="toolTip">
+            <string>Enter the network name (SSID) to connect to</string>
+           </property>
+           <property name="clearButtonEnabled">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0">
+          <widget class="QLabel" name="label_9">
+           <property name="text">
+            <string>Password:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="1">
+          <widget class="QLineEdit" name="passwordEdit">
+           <property name="toolTip">
+            <string>Enter the network password</string>
+           </property>
+           <property name="echoMode">
+            <enum>QLineEdit::Password</enum>
+           </property>
+           <property name="clearButtonEnabled">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="2">
+          <widget class="QToolButton" name="showPasswordButton">
+           <property name="toolTip">
+            <string>Press to show the password</string>
+           </property>
+           <property name="checkable">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+      <item>
+       <widget class="QGroupBox" name="groupBox_15">
+        <property name="title">
+         <string>Access Point</string>
+        </property>
+        <layout class="QGridLayout" name="gridLayout_10">
+         <item row="0" column="0">
+          <widget class="QLabel" name="label_10">
+           <property name="text">
+            <string>Name:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1" colspan="2">
+          <widget class="QLineEdit" name="apSsidEdit">
+           <property name="toolTip">
+            <string>Enter the network name (SSID) to publish</string>
+           </property>
+           <property name="clearButtonEnabled">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0">
+          <widget class="QLabel" name="label_12">
+           <property name="text">
+            <string>Password:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="1">
+          <widget class="QLineEdit" name="apPasswordEdit">
+           <property name="toolTip">
+            <string>Enter the network password</string>
+           </property>
+           <property name="echoMode">
+            <enum>QLineEdit::Password</enum>
+           </property>
+           <property name="clearButtonEnabled">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="2">
+          <widget class="QToolButton" name="apShowPasswordButton">
+           <property name="toolTip">
+            <string>Press to show the password</string>
+           </property>
+           <property name="checkable">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="0">
+          <widget class="QLabel" name="label_23">
+           <property name="text">
+            <string>Security:</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1" colspan="2">
+          <layout class="QHBoxLayout" name="horizontalLayout_6">
+           <item>
+            <widget class="QComboBox" name="apSecurityComboBox">
+             <property name="toolTip">
+              <string>Select the security mode</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <spacer name="horizontalSpacer_3">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>40</width>
+               <height>20</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+          </layout>
+         </item>
+         <item row="3" column="0" colspan="3">
+          <widget class="QGroupBox" name="ipv4GroupBox">
+           <property name="focusPolicy">
+            <enum>Qt::NoFocus</enum>
+           </property>
+           <property name="title">
+            <string>IPv4 Configuration</string>
+           </property>
+           <layout class="QHBoxLayout" name="horizontalLayout_7">
+            <item>
+             <layout class="QGridLayout" name="gridLayout_9">
+              <item row="0" column="0">
+               <widget class="QLabel" name="label_24">
+                <property name="text">
+                 <string>Address:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1">
+               <widget class="EricIPv4InputWidget" name="apAddressEdit" native="true">
+                <property name="focusPolicy">
+                 <enum>Qt::NoFocus</enum>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="0">
+               <widget class="QLabel" name="label_25">
+                <property name="text">
+                 <string>Netmask:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="1" column="1">
+               <widget class="EricIPv4InputWidget" name="apNetmaskEdit" native="true">
+                <property name="focusPolicy">
+                 <enum>Qt::NoFocus</enum>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="0">
+               <widget class="QLabel" name="label_26">
+                <property name="text">
+                 <string>Gateway:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="2" column="1">
+               <widget class="EricIPv4InputWidget" name="apGatewayEdit" native="true">
+                <property name="focusPolicy">
+                 <enum>Qt::NoFocus</enum>
+                </property>
+               </widget>
+              </item>
+              <item row="3" column="0">
+               <widget class="QLabel" name="label_27">
+                <property name="text">
+                 <string>DNS:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="3" column="1">
+               <widget class="EricIPv4InputWidget" name="apDnsEdit" native="true">
+                <property name="focusPolicy">
+                 <enum>Qt::NoFocus</enum>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_4">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>273</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+           </layout>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
     <widget class="QGroupBox" name="groupBox_3">
      <property name="title">
       <string>MPY Cross Compiler</string>
@@ -545,6 +825,12 @@
    <header>eric7/EricWidgets/EricPathPicker.h</header>
    <container>1</container>
   </customwidget>
+  <customwidget>
+   <class>EricIPv4InputWidget</class>
+   <extends>QWidget</extends>
+   <header>eric7/EricNetwork/EricIPv4InputWidget.h</header>
+   <container>1</container>
+  </customwidget>
  </customwidgets>
  <tabstops>
   <tabstop>workspacePicker</tabstop>
@@ -554,6 +840,15 @@
   <tabstop>colorSchemeComboBox</tabstop>
   <tabstop>replWrapCheckBox</tabstop>
   <tabstop>chartThemeComboBox</tabstop>
+  <tabstop>countryEdit</tabstop>
+  <tabstop>ssidEdit</tabstop>
+  <tabstop>passwordEdit</tabstop>
+  <tabstop>showPasswordButton</tabstop>
+  <tabstop>apSsidEdit</tabstop>
+  <tabstop>apPasswordEdit</tabstop>
+  <tabstop>apShowPasswordButton</tabstop>
+  <tabstop>apSecurityComboBox</tabstop>
+  <tabstop>ipv4GroupBox</tabstop>
   <tabstop>mpyCrossPicker</tabstop>
   <tabstop>dfuUtilPathPicker</tabstop>
   <tabstop>micropythonFirmwareUrlLineEdit</tabstop>
--- a/src/eric7/Preferences/__init__.py	Wed Mar 01 09:03:13 2023 +0100
+++ b/src/eric7/Preferences/__init__.py	Fri Mar 03 11:31:53 2023 +0100
@@ -1576,6 +1576,16 @@
         "DfuUtilPath": "",  # path of the dfu-util flashing tool
         "IgnoredUnknownDevices": "[]",  # empty list encoded as JSON
         "ManualDevices": "[]",  # empty list encoded as JSON
+        "WifiName": "",
+        "WifiPassword": "",
+        "WifiApName": "",
+        "WifiApPassword": "",
+        "WifiApAuthMode": 4,  # WPA/WPA2
+        "WifiApAddress": "",
+        "WifiApNetmask": "",
+        "WifiApGateway": "",
+        "WifiApDNS": "",
+        "WifiCountry": "",
         # MicroPython URLs
         "MicroPythonDocuUrl": "https://docs.micropython.org/en/latest/",
         "MicroPythonFirmwareUrl": "http://micropython.org/download/",
@@ -3777,7 +3787,7 @@
     @param key the key of the value to get
     @return the requested MicroPython value
     """
-    if key in ("SerialTimeout", "ChartColorTheme"):
+    if key in ("SerialTimeout", "ChartColorTheme", "WifiApAuthMode"):
         return int(
             Prefs.settings.value("MicroPython/" + key, Prefs.microPythonDefaults[key])
         )
@@ -3799,6 +3809,11 @@
             return json.loads(jsonStr)
         else:
             return None
+    elif key in ("WifiPassword", "WifiApPassword"):
+        return pwConvert(
+            Prefs.settings.value("MicroPython/" + key, Prefs.microPythonDefaults[key]),
+            encode=False,
+        )
     else:
         return Prefs.settings.value(
             "MicroPython/" + key, Prefs.microPythonDefaults[key]
@@ -3814,6 +3829,8 @@
     """
     if key in ["IgnoredUnknownDevices", "ManualDevices"]:
         Prefs.settings.setValue("MicroPython/" + key, json.dumps(value))
+    elif key in ("WifiPassword", "WifiApPassword"):
+        Prefs.settings.setValue("MicroPython/" + key, pwConvert(value, encode=True))
     else:
         Prefs.settings.setValue("MicroPython/" + key, value)
 

eric ide

mercurial