diff -r 5f84d5eeee9e -r 163511257f24 src/eric7/MicroPython/Devices/RP2040Devices.py --- a/src/eric7/MicroPython/Devices/RP2040Devices.py Tue Feb 21 10:53:46 2023 +0100 +++ b/src/eric7/MicroPython/Devices/RP2040Devices.py Wed Feb 22 07:45:54 2023 +0100 @@ -11,6 +11,7 @@ import ast import binascii import json +import os from PyQt6.QtCore import QUrl, pyqtSlot from PyQt6.QtNetwork import QNetworkRequest @@ -506,13 +507,13 @@ if self._deviceData["wifi_type"] == "picow": country = Preferences.getMicroPython("WifiCountry").upper() command = """ -def connect_wifi(ssid, password): +def connect_wifi(ssid, password, country): import network import rp2 import ujson from time import sleep - rp2.country({2}) + rp2.country(country) wifi = network.WLAN(network.STA_IF) wifi.active(False) @@ -527,7 +528,7 @@ status = wifi.status() print(ujson.dumps({{'connected': wifi.isconnected(), 'status': status}})) -connect_wifi({0}, {1}) +connect_wifi({0}, {1}, {2}) del connect_wifi """.format( repr(ssid), @@ -592,6 +593,86 @@ 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 '""', + ) + 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) + 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. @@ -641,9 +722,13 @@ @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() @@ -656,7 +741,8 @@ scan_networks() del scan_networks -""" +""".format(repr(country if country else "XX")) + elif self._deviceData["wifi_type"] == "pimoroni": # TODO: not yet implemented pass @@ -725,13 +811,55 @@ else: return out.decode("utf-8").strip() == "True", "" - def startAccessPoint(self): + def startAccessPoint(self, ssid, security=None, password=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) @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(): + import network + import rp2 + from time import sleep + + rp2.country({3}) + + ap = network.WLAN(network.AP_IF) + ap.config(ssid={0}, security={1}, password={2}) + ap.active(True) + sleep(0.1) + print(ap.isconnected()) + +start_ap() +del start_ap +""".format(repr(ssid), security, repr(password), repr(country if country else "XX")) + elif self._deviceData["wifi_type"] == "pimoroni": + # TODO: not yet implemented + pass + else: + return super().startAccessPoint(ssid, security=security, password=password) + + out, err = self._interface.execute(command, timeout=15000) + if err: + return False, err + else: + return out.decode("utf-8").strip() == "True", "" def stopAccessPoint(self): """ @@ -748,6 +876,39 @@ 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"] == "pimoroni": + # TODO: not yet implemented + pass + else: + return super().checkInternet() + + out, err = self._interface.execute(command, timeout=10000) + if err: + return [], err + + clientsList = ast.literal_eval(out.decode("utf-8")) + return clientsList, "" + ############################################################################ ## RP2 only methods below ############################################################################ @@ -774,7 +935,7 @@ out, err = self._interface.execute(command) if err: - self._showError("rp2.country()", err) + self.microPython.showError("rp2.country()", err) def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber):