src/eric7/MicroPython/Devices/RP2040Devices.py

branch
mpy_network
changeset 9878
a82014a9e57b
parent 9870
0399d3607829
child 9880
f425c58cf8e9
diff -r dad1f6d37366 -r a82014a9e57b src/eric7/MicroPython/Devices/RP2040Devices.py
--- a/src/eric7/MicroPython/Devices/RP2040Devices.py	Sat Mar 11 15:28:47 2023 +0100
+++ b/src/eric7/MicroPython/Devices/RP2040Devices.py	Sun Mar 12 14:56:04 2023 +0100
@@ -22,6 +22,7 @@
 from eric7.EricWidgets import EricMessageBox
 from eric7.EricWidgets.EricApplication import ericApp
 
+from ..EthernetDialogs import WiznetUtilities
 from ..MicroPythonWidget import HAS_QTCHART
 from . import FirmwareGithubUrls
 from .DeviceBase import BaseDevice
@@ -69,6 +70,11 @@
                 8: self.tr("AP connected"),
                 9: self.tr("AP failed"),
             },
+            "picowiz": {
+                0: self.tr("switched off"),
+                1: self.tr("switched on, inactive"),
+                2: self.tr("switched on, active"),
+            },
         }
 
         self.__securityTranslations = {
@@ -1175,6 +1181,292 @@
         return clientsList, ""
 
     ##################################################################
+    ## 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
+        @exception OSError raised to indicate an issue with the device
+        """
+        command = """
+def has_eth():
+    try:
+        import network
+        if hasattr(network, 'WIZNET5K'):
+            return True, 'picowiz'
+    except ImportError:
+        pass
+
+    return False, ''
+
+print(has_eth())
+del has_eth
+"""
+
+        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 getEthernetStatus(self):
+        """
+        Public method to get Ethernet status data of the connected board.
+
+        @return list of tuples containing the translated status data label and
+            the associated value
+        @rtype list of tuples of (str, str)
+        @exception OSError raised to indicate an issue with the device
+        """
+        command = """{0}
+def ethernet_status():
+    import network
+    import ubinascii
+    import ujson
+
+    w5x00_init()
+
+    res = {{
+        'active': nic.active(),
+        'connected': nic.isconnected(),
+        'status': nic.status(),
+        'ifconfig': nic.ifconfig(),
+        'mac': ubinascii.hexlify(nic.config('mac'), ':').decode(),
+        'hostname': network.hostname(),
+    }}
+    print(ujson.dumps(res))
+
+ethernet_status()
+del ethernet_status, w5x00_init
+""".format(
+            WiznetUtilities.wiznetInit()
+        )
+
+        out, err = self._interface.execute(command, mode=self._submitMode)
+        if err:
+            raise OSError(self._shortError(err))
+
+        status = []
+        ethStatus = json.loads(out.decode("utf-8"))
+        status.append((self.tr("Active"), self.bool2str(ethStatus["active"])))
+        status.append((self.tr("Connected"), self.bool2str(ethStatus["connected"])))
+        status.append(
+            (
+                self.tr("Status"),
+                self.__statusTranslations["picowiz"][ethStatus["status"]],
+            )
+        )
+        status.append((self.tr("Hostname"), ethStatus["hostname"]))
+        status.append((self.tr("IPv4 Address"), ethStatus["ifconfig"][0]))
+        status.append((self.tr("Netmask"), ethStatus["ifconfig"][1]))
+        status.append((self.tr("Gateway"), ethStatus["ifconfig"][2]))
+        status.append((self.tr("DNS"), ethStatus["ifconfig"][3]))
+        status.append((self.tr("MAC-Address"), ethStatus["mac"]))
+
+        return status
+
+    def connectToLan(self, config):
+        """
+        Public method to connect the connected device to the LAN.
+
+        @param config configuration for the connection (either the string 'dhcp'
+            for a dynamic address or a tuple of four strings with the IPv4 parameters.
+        @type str or tuple of (str, str, str, str)
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        command = """{0}
+def connect_lan(config):
+    import time
+
+    w5x00_init()
+
+    nic.active(False)
+    nic.active(True)
+    nic.ifconfig(config)
+    max_wait = 140
+    while max_wait:
+        if nic.isconnected():
+            break
+        max_wait -= 1
+        time.sleep(0.1)
+    print(nic.isconnected())
+
+connect_lan({1})
+del connect_lan, w5x00_init
+""".format(
+            WiznetUtilities.wiznetInit(), repr(config) if config == "dhcp" else config
+        )
+
+        with EricOverrideCursor():
+            out, err = self._interface.execute(
+                command, mode=self._submitMode, timeout=15000
+            )
+        if err:
+            return False, err
+
+        return out.strip() == b"True", ""
+
+    def disconnectFromLan(self):
+        """
+        Public method  to disconnect from the LAN.
+
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        command = """{0}
+def disconnect_lan():
+    import time
+
+    w5x00_init()
+
+    nic.active(False)
+    time.sleep(0.1)
+    print(not nic.isconnected())
+
+disconnect_lan()
+del disconnect_lan, w5x00_init
+""".format(
+            WiznetUtilities.wiznetInit(),
+        )
+
+        with EricOverrideCursor():
+            out, err = self._interface.execute(
+                command, mode=self._submitMode, timeout=15000
+            )
+        if err:
+            return False, err
+
+        return out.strip() == b"True", ""
+
+    def checkInternetViaLan(self):
+        """
+        Public method to check, if the internet can be reached (LAN variant).
+
+        @return tuple containing a flag indicating reachability and an error string
+        @rtype tuple of (bool, str)
+        """
+        command = """{0}
+def check_internet():
+    import network
+    import socket
+
+    w5x00_init()
+
+    if nic.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, w5x00_init
+""".format(
+            WiznetUtilities.wiznetInit(),
+        )
+
+        out, err = self._interface.execute(
+            command, mode=self._submitMode, timeout=10000
+        )
+        if err:
+            return False, err
+
+        return out.strip() == b"True", ""
+
+    def deactivateEthernet(self):
+        """
+        Public method to deactivate the Ethernet interface of the connected device.
+
+        @return tuple containg a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        # The WIZnet 5x00 interface cannot be switched off explicitly. That means,
+        # disconnect from the LAN is all we can do.
+
+        return self.disconnectFromLan()
+
+    def writeLanAutoConnect(self, config):
+        """
+        Public method to generate a script and associated configuration to connect the
+        device to the LAN during boot time.
+
+        @param config configuration for the connection (either the string 'dhcp'
+            for a dynamic address or a tuple of four strings with the IPv4 parameters.
+        @type str or tuple of (str, str, str, 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 'wiznet_connect' in ln:
+                    add = False
+                    break
+    except:
+        pass
+    if add:
+        with open('/boot.py', 'a') as f:
+            f.write('\\nimport wiznet_connect\\n')
+            f.write('nic = wiznet_connect.connectLan()\\n')
+    print(True)
+
+modify_boot()
+del modify_boot
+"""
+        ifconfig = "ifconfig = {0}\n".format("'dhcp'" if config == "dhcp" else config)
+        try:
+            # write secrets file
+            self.putData("/wiznet_config.py", ifconfig.encode("utf-8"))
+            # copy auto-connect file
+            self.put(
+                os.path.join(
+                    os.path.dirname(__file__), "MCUScripts", "picoWiznetConnect.py"
+                ),
+                "/wiznet_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 removeLanAutoConnect(self):
+        """
+        Public method to remove the saved IPv4 parameters from the connected device.
+
+        Note: This disables the LAN auto-connect feature.
+
+        @return tuple containing a flag indicating success and an error message
+        @rtype tuple of (bool, str)
+        """
+        try:
+            self.rm("/wiznet_config.py")
+        except OSError as err:
+            return False, str(err)
+
+        return True, ""
+
+    ##################################################################
     ## Methods below implement NTP related methods
     ##################################################################
 
@@ -1224,8 +1516,14 @@
     import ntptime
     import machine
 
-    if not network.WLAN(network.STA_IF).isconnected():
+    if hasattr(network, 'WLAN') and not network.WLAN(network.STA_IF).isconnected():
         return False
+    elif hasattr(network, 'WIZNET5K'):
+        try:
+            if not nic.isconnected():
+                return False
+        except NameError:
+            return False
 
     ntptime.host = server
     ntptime.timeout = timeout

eric ide

mercurial