Fri, 25 Apr 2025 16:23:02 +0200
MicroPython
- Extended the handling of Access Point security/authmode settings to be more dynamic.
--- a/src/eric7/MicroPython/Devices/CircuitPythonDevices.py Fri Apr 25 16:22:02 2025 +0200 +++ b/src/eric7/MicroPython/Devices/CircuitPythonDevices.py Fri Apr 25 16:23:02 2025 +0200 @@ -98,16 +98,20 @@ "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]", + "SEC_OPEN": "[wifi.AuthMode.OPEN]", + "SEC_WEP": "[wifi.AuthMode.WEP]", + "SEC_WPA": "[wifi.AuthMode.WPA, wifi.AuthMode.PSK]", + "SEC_WPA2": "[wifi.AuthMode.WPA2, wifi.AuthMode.PSK]", + "SEC_WPA_WPA2": "[wifi.AuthMode.WPA, wifi.AuthMode.WPA2, wifi.AuthMode.PSK]", + # noqa: E-501 + "SEC_WPA2_ENT": "[wifi.AuthMode.WPA2, wifi.AuthMode.ENTERPRISE]", + "SEC_WPA3": "[wifi.AuthMode.WPA3, wifi.AuthMode.PSK]", + "SEC_WPA2_WPA3": "[wifi.AuthMode.WPA2, wifi.AuthMode.WPA3, wifi.AuthMode.PSK]", + # noqa: E-501 } + self.__bleAddressType = { 0: self.tr("Public"), 1: self.tr("Random Static"), @@ -1237,8 +1241,8 @@ @param ssid SSID of the access point @type str - @param security security method (defaults to None) - @type int (optional) + @param security security mode (defaults to None) (unused) + @type str (optional) @param password password (defaults to None) @type str (optional) @param hostname host name of the device (defaults to None) @@ -1250,7 +1254,7 @@ @rtype tuple of (bool, str) """ if security is None or password is None: - security = 0 + security = "SEC_OPEN" password = "" # secok authmode = self.__securityCode2AuthModeString[security] @@ -1332,6 +1336,15 @@ self.tr("CircuitPython does not support reporting of connected clients."), ) + def getSecurityModes(self): + """ + Public method to get a list of security modes supported by the device. + + @return list of supported security modes + @rtype list of str + """ + return list(self.__securityCode2AuthModeString.keys()) + ################################################################## ## Methods below implement Ethernet related methods ##################################################################
--- a/src/eric7/MicroPython/Devices/DeviceBase.py Fri Apr 25 16:22:02 2025 +0200 +++ b/src/eric7/MicroPython/Devices/DeviceBase.py Fri Apr 25 16:23:02 2025 +0200 @@ -82,6 +82,9 @@ <li>startAccessPoint: start an access point</li> <li>stopAccessPoint: stop the access point</li> <li>getConnectedClients: get a list of connected WiFi clients</li> + <li>getSecurityModes: get a list of supported security modes</li> + <li>enableWebrepl + <li>disableWebrepl </ul> Supported Bluetooth commands are: @@ -1911,8 +1914,8 @@ @param ssid SSID of the access point (unused) @type str - @param security security method (defaults to None) (unused) - @type int (optional) + @param security security mode (defaults to None) (unused) + @type str (optional) @param password password (defaults to None) (unused) @type str (optional) @param hostname host name of the device (defaults to None) (unused) @@ -1944,6 +1947,28 @@ """ return [], "" + def getSecurityModes(self): + """ + Public method to get a list of security modes supported by the device. + + @return list of supported security modes + @rtype list of str + """ + command = """ +def getSecurityModes(): + import network + modes = [s for s in dir(network.WLAN) if s.startswith('SEC_')] + return modes + +print(getSecurityModes()) +del getSecurityModes +""" + out, err = self.executeCommands(command, mode=self._submitMode) + if err: + return [] + + return ast.literal_eval(out.decode("utf-8")) + def enableWebrepl(self, password): # noqa: U-100 """ Public method to write the given WebREPL password to the connected device and @@ -1958,8 +1983,7 @@ def disableWebrepl(self): """ - Public method to write the given WebREPL password to the connected device and - modify the start script to start the WebREPL server. + Public method to modify the start script to not start the WebREPL server. @return tuple containing a flag indicating success and an error message @rtype tuple of (bool, str)
--- a/src/eric7/MicroPython/Devices/EspDevices.py Fri Apr 25 16:22:02 2025 +0200 +++ b/src/eric7/MicroPython/Devices/EspDevices.py Fri Apr 25 16:23:02 2025 +0200 @@ -76,6 +76,24 @@ 6: "WPA3", 7: "WPA2/WPA3", } + self.__securityMapping = { + "SEC_DPP": "DPP", + "SEC_OPEN": self.tr("Open"), + "SEC_OWE": "OWE", + "SEC_WAPI": "WAPI", + "SEC_WEP": "WEP", + "SEC_WPA": "WPA", + "SEC_WPA_WPA2": "WPA/WPA2", + "SEC_WPA2": "WPA2", + "SEC_WPA2_ENT": "WPA2 Enterprise", + "SEC_WPA2_WPA3": "WPA2/WPA3", + "SEC_WPA2_WPA3_ENT": "WPA2/WPA3 Enterprise", + "SEC_WPA3": "WPA3", + "SEC_WPA3_ENT": "WPA3 Enterprise", + "SEC_WPA3_ENT_192": "WPA3 Enterprise (192-bit)", + "SEC_WPA3_EXT_PSK": "WPA3 Extended", + "SEC_WPA3_EXT_PSK_MIXED_MODE": "WPA3 Extended, Mixed Mode", + } def __createCpyDevice(self): """ @@ -718,6 +736,12 @@ import ujson import network + def security_str(mode): + for sm in [e for e in dir(network.WLAN) if e.startswith('SEC_')]: + if getattr(network.WLAN, sm, 0) == mode: + return sm + return "" + wifi = network.WLAN(network.STA_IF) station = { 'active': wifi.active(), @@ -742,6 +766,7 @@ 'mac': ubinascii.hexlify(wifi.config('mac'), ':').decode(), 'channel': wifi.config('channel'), 'essid': wifi.config('essid'), + 'ap_security': security_str(wifi.config('security')), } if wifi.active(): try: @@ -783,6 +808,11 @@ ap["status"] = self.__statusTranslations[ap["status"]] except KeyError: ap["status"] = str(ap["status"]) + if "ap_security" in ap: + try: + ap["ap_security"] = self.__securityMapping[ap["ap_security"]] + except KeyError: + ap["ap_security"] = self.tr("unknown ({0})").format(ap["ap_security"]) return station, ap, overall def connectWifi(self, ssid, password, hostname): @@ -1188,8 +1218,8 @@ @param ssid SSID of the access point @type str - @param security security method (defaults to None) - @type int (optional) + @param security security mode (defaults to None) (unused) + @type str (optional) @param password password (defaults to None) @type str (optional) @param hostname host name of the device (defaults to None) @@ -1210,13 +1240,11 @@ ) if security is None or password is None: - security = 0 + security = "SEC_OPEN" password = "" # secok - if security > 4: - security = 4 # security >4 cause an error thrown by the ESP32 command = """ -def start_ap(ssid, authmode, password, hostname, ifconfig): +def start_ap(ssid, password, hostname, ifconfig): import network if hostname: @@ -1231,14 +1259,14 @@ ap.ifconfig(ifconfig) ap.active(True) try: - ap.config(ssid=ssid, authmode=authmode, password=password) + ap.config(ssid=ssid, authmode=network.WLAN.{4}, password=password) except: - ap.config(essid=ssid, authmode=authmode, password=password) + ap.config(essid=ssid, authmode=network.WLAN.{4}, password=password) -start_ap({0}, {1}, {2}, {3}, {4}) +start_ap({0}, {1}, {2}, {3}) del start_ap """.format( - repr(ssid), security, repr(password), repr(hostname), ifconfig + repr(ssid), repr(password), repr(hostname), ifconfig, security ) out, err = self.executeCommands(command, mode=self._submitMode, timeout=15000)
--- a/src/eric7/MicroPython/Devices/RP2Devices.py Fri Apr 25 16:22:02 2025 +0200 +++ b/src/eric7/MicroPython/Devices/RP2Devices.py Fri Apr 25 16:23:02 2025 +0200 @@ -98,6 +98,25 @@ }, } + self.__securityMapping = { + "SEC_DPP": "DPP", + "SEC_OPEN": self.tr("Open"), + "SEC_OWE": "OWE", + "SEC_WAPI": "WAPI", + "SEC_WEP": "WEP", + "SEC_WPA": "WPA", + "SEC_WPA_WPA2": "WPA/WPA2", + "SEC_WPA2": "WPA2", + "SEC_WPA2_ENT": "WPA2 Enterprise", + "SEC_WPA2_WPA3": "WPA2/WPA3", + "SEC_WPA2_WPA3_ENT": "WPA2/WPA3 Enterprise", + "SEC_WPA3": "WPA3", + "SEC_WPA3_ENT": "WPA3 Enterprise", + "SEC_WPA3_ENT_192": "WPA3 Enterprise (192-bit)", + "SEC_WPA3_EXT_PSK": "WPA3 Extended", + "SEC_WPA3_EXT_PSK_MIXED_MODE": "WPA3 Extended, Mixed Mode", + } + def setButtons(self): """ Public method to enable the supported action buttons. @@ -560,6 +579,12 @@ import network import rp2 + def security_str(mode): + for sm in [e for e in dir(network.WLAN) if e.startswith('SEC_')]: + if getattr(network.WLAN, sm, 0) == mode: + return sm + return "" + wifi = network.WLAN(network.STA_IF) station = { 'active': wifi.active(), @@ -582,6 +607,7 @@ 'channel': wifi.config('channel'), 'txpower': wifi.config('txpower'), 'essid': wifi.config('essid'), + 'ap_security': security_str(wifi.config('security')), } print(ujson.dumps(ap)) @@ -698,6 +724,12 @@ station["ap_security"] = self.tr("unknown ({0})").format( station["ap_security"] ) + if "ap_security" in ap and self._deviceData["wifi_type"] == "picow": + try: + ap["ap_security"] = self.__securityMapping[ap["ap_security"]] + except KeyError: + ap["ap_security"] = self.tr("unknown ({0})").format(ap["ap_security"]) + return station, ap, overall def connectWifi(self, ssid, password, hostname): @@ -1219,8 +1251,8 @@ @param ssid SSID of the access point @type str - @param security security method (defaults to None) - @type int (optional) + @param security security mode (defaults to None) (unused) + @type str (optional) @param password password (defaults to None) @type str (optional) @param hostname host name of the device (defaults to None) @@ -1232,15 +1264,13 @@ @rtype tuple of (bool, str) """ if security is None or password is None: - security = 0 + security = "SEC_OPEN" password = "" # secok 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, hostname, ifconfig, country): +def start_ap(ssid, password, hostname, ifconfig, country): import network import rp2 from time import sleep @@ -1257,19 +1287,19 @@ ap.active(True) if ifconfig: ap.ifconfig(ifconfig) - ap.config(ssid=ssid, security=security, password=password) + ap.config(ssid=ssid, security=network.WLAN.{5}, password=password) sleep(0.1) print(ap.status() == network.STAT_GOT_IP) -start_ap({0}, {1}, {2}, {3}, {4}, {5}) +start_ap({0}, {1}, {2}, {3}, {4}) del start_ap """.format( repr(ssid), - security, repr(password), repr(hostname), ifconfig, repr(country if country else "XX"), + security, ) elif self._deviceData["wifi_type"] == "picowireless": if ifconfig:
--- a/src/eric7/MicroPython/WifiDialogs/WifiApConfigDialog.py Fri Apr 25 16:22:02 2025 +0200 +++ b/src/eric7/MicroPython/WifiDialogs/WifiApConfigDialog.py Fri Apr 25 16:23:02 2025 +0200 @@ -21,29 +21,50 @@ Class implementing a dialog to configure the Access Point interface. """ - def __init__(self, withIP, parent=None): + def __init__(self, withIP, securityModes, parent=None): """ Constructor @param withIP flag indicating to ask the user for an IP configuration @type bool + @param securityModes list of supported security modes + @type list of str @param parent reference to the parent widget (defaults to None) @type QWidget (optional) """ super().__init__(parent) self.setupUi(self) + self.__securityMapping = { + "SEC_DPP": "DPP", + "SEC_OPEN": self.tr("Open"), + "SEC_OWE": "OWE", + "SEC_WAPI": "WAPI", + "SEC_WEP": "WEP", + "SEC_WPA": "WPA", + "SEC_WPA_WPA2": "WPA/WPA2", + "SEC_WPA2": "WPA2", + "SEC_WPA2_ENT": "WPA2 Enterprise", + "SEC_WPA2_WPA3": "WPA2/WPA3", + "SEC_WPA2_WPA3_ENT": "WPA2/WPA3 Enterprise", + "SEC_WPA3": "WPA3", + "SEC_WPA3_ENT": "WPA3 Enterprise", + "SEC_WPA3_ENT_192": "WPA3 Enterprise (192-bit)", + "SEC_WPA3_EXT_PSK": "WPA3 Extended", + "SEC_WPA3_EXT_PSK_MIXED_MODE": "WPA3 Extended, Mixed Mode", + } + 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) + for securityMode in sorted(securityModes): + try: + self.apSecurityComboBox.addItem( + self.__securityMapping[securityMode], securityMode + ) + except KeyError: + self.apSecurityComboBox.addItem(securityMode, securityMode) + self.apSecurityComboBox.model().sort(0) self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False) @@ -54,7 +75,8 @@ Preferences.getMicroPython("WifiApAuthMode") ) if index == -1: - index = 5 # default it to WPA/WPA2 in case of an issue + index = self.apSecurityComboBox.findData("SEC_WPA_WPA2") + # default it to WPA/WPA2 in case of an issue self.apSecurityComboBox.setCurrentIndex(index) self.hostnameEdit.setText(Preferences.getMicroPython("WifiApHostname")) @@ -90,7 +112,7 @@ Private method to update the enabled state of the OK button. """ enable = bool(self.apSsidEdit.text()) - if self.apSecurityComboBox.currentData() != 0: + if self.apSecurityComboBox.currentData() != "SEC_OPEN": # security needs a password enable &= bool(self.apPasswordEdit.text()) if self.__withIP: @@ -138,6 +160,8 @@ Preferences.setMicroPython("WifiApGateway", self.gatewayEdit.text()) Preferences.setMicroPython("WifiApDNS", self.dnsEdit.text()) + Preferences.syncPreferences() + super().accept() def getApConfig(self):
--- a/src/eric7/MicroPython/WifiDialogs/WifiController.py Fri Apr 25 16:22:02 2025 +0200 +++ b/src/eric7/MicroPython/WifiDialogs/WifiController.py Fri Apr 25 16:23:02 2025 +0200 @@ -302,13 +302,16 @@ """ from .WifiApConfigDialog import WifiApConfigDialog - dlg = WifiApConfigDialog(withIP=withIP, parent=self.__mpy) + securityModes = self.__mpy.getDevice().getSecurityModes() + dlg = WifiApConfigDialog( + withIP=withIP, securityModes=securityModes, parent=self.__mpy + ) if dlg.exec() == QDialog.DialogCode.Accepted: - ssid, password, security, hostname, ifconfig = dlg.getApConfig() + ssid, password, securityMode, hostname, ifconfig = dlg.getApConfig() ok, err = self.__mpy.getDevice().startAccessPoint( ssid, - security=security, + security=securityMode, password=password, hostname=hostname, ifconfig=ifconfig if withIP else None,
--- a/src/eric7/MicroPython/WifiDialogs/WifiStatusDialog.py Fri Apr 25 16:22:02 2025 +0200 +++ b/src/eric7/MicroPython/WifiDialogs/WifiStatusDialog.py Fri Apr 25 16:23:02 2025 +0200 @@ -183,6 +183,10 @@ QTreeWidgetItem(header, [self.tr("DNS"), apStatus["ifconfig"][3]]) with contextlib.suppress(KeyError): QTreeWidgetItem(header, [self.tr("SSID"), apStatus["essid"]]) + with contextlib.suppress(KeyError): + QTreeWidgetItem( + header, [self.tr("Security"), apStatus["ap_security"]] + ) QTreeWidgetItem(header, [self.tr("MAC-Address"), apStatus["mac"]]) with contextlib.suppress(KeyError): QTreeWidgetItem(
--- a/src/eric7/Preferences/__init__.py Fri Apr 25 16:22:02 2025 +0200 +++ b/src/eric7/Preferences/__init__.py Fri Apr 25 16:23:02 2025 +0200 @@ -1556,7 +1556,7 @@ "WifiHostname": "", "WifiApName": "", "WifiApPassword": "", - "WifiApAuthMode": 4, # WPA/WPA2 + "WifiApAuthMode": "SEC_WPA_WPA2", "WifiApHostname": "", "WifiApAddress": "", "WifiApNetmask": "", @@ -3940,7 +3940,6 @@ "SerialTimeout", "WebreplTimeout", "ChartColorTheme", - "WifiApAuthMode", "NtpOffset", "NtpTimeout", ):