src/eric7/MicroPython/WifiDialogs/WifiController.py

Mon, 20 Feb 2023 16:02:02 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 20 Feb 2023 16:02:02 +0100
branch
mpy_network
changeset 9782
67414f28db68
parent 9781
3112f77f722b
child 9787
163511257f24
permissions
-rw-r--r--

Continued implementing WiFi functionality for RP2040 based devices (interface deactivation, AP stop, MicroPython config page).

# -*- 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.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("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 = self.__mpy.getDevice().getWifiData()

            dlg = WifiStatusDialog(clientStatus, apStatus)
            dlg.exec()
        except Exception as exc:
            self.__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.
        """
        # TODO: not implemented yet
        pass

    @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.
        """
        # TODO: not implemented yet
        pass

    @pyqtSlot()
    def __startAccessPoint(self):
        """
        Private slot to start the Access Point interface of the connected device.
        """
        # TODO: not implemented yet
        pass

    @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.
        """
        # TODO: not implemented yet
        pass

    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,
            )

eric ide

mercurial