Thursday, April 14, 2022

[SOLVED] Python: Getting current Connection Type (Lan, Wifi, Mobile(sim card)) of device

Issue

I would like to know how to get the current Connection type of the device where the python script will be running from this can only be three types as far as I know.

  • Lan= Wired
  • Wifi = Wireless
  • Mobile= By Sim Card.

Is this possible? If so can anyone plese put me in the right direction? Because I have trouble finding something that can help me.

The device itself is a RaspBerry Pi 4B.

Edit: I would also like to know if which of these devices are being used to connect A interface can be "up" but might not be the primary interface that is being used to connect. This is to get a boolean back for certain functions.


Solution

I would recommend using psutil.net_if_stats(), psutil is cross-platform and should work fine on any devices.

  • List NIC devices stats dictionary by psutil.net_if_stats()
  • Filter devices with isup=True
  • See if Wifi, Lan or Mobile is up (would be wlan0, eth or enp in linux - not sure about mobile)
>>> import psutil
>>> from pprint import pprint

>>> nets = psutil.net_if_stats()
>>> pprint(nets)
{'Bluetooth 네트워크 연결': snicstats(isup=False, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=3, mtu=1500),
 'Loopback Pseudo-Interface 1': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=1073, mtu=1500),
 'Wi-Fi': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=432, mtu=1500),
 'vEthernet (WSL)': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=4294, mtu=1500),
 '로컬 영역 연결* 1': snicstats(isup=False, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=0, mtu=1500),
 '로컬 영역 연결* 10': snicstats(isup=False, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=0, mtu=1500),
 '이더넷': snicstats(isup=False, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=2500, mtu=1500)}

>>> active_nets = {name: net_stat for name, net_stat in nets.items() if net_stat.isup}
>>> pprint(active_nets)
{'Loopback Pseudo-Interface 1': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=1073, mtu=1500),
 'Wi-Fi': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=432, mtu=1500),
 'vEthernet (WSL)': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=4294, mtu=1500)}
>>>

And to get address, psutil.net_if_addrs() is here to help.

With these, we can get active NIC's name, and it's IPs.

from typing import Tuple, List
from socket import AF_LINK, AF_INET, AF_INET6

import psutil


class NetworkInterfaceNotFound(Exception):
    pass


def get_active_nets():
    """
    Get active NIC names.

    Returns:
        Set of active NIC names.
    """

    return {name for name, net in psutil.net_if_stats().items() if net.isup}


def determine_current_nic(*net_names) -> Tuple[str, str, List[str], List[str]]:
    """
    Determine primary active NIC.

    Notes:
        One NIC may have multiple addresses of same family. Thus returning in list.

    Args:
        *net_names: NIC names to look for. NIC priority == item order

    Returns:
        NIC's Name, MAC, IPv4 address list, IPv6 address list
    """

    types = {
        AF_LINK.name: [],
        AF_INET.name: [],
        AF_INET6.name: [],
    }

    active_nets = get_active_nets()
    address_dict = psutil.net_if_addrs()

    matching_name = ""

    for net_name in net_names:

        if net_name in active_nets:
            # now we have the device.
            matching_name = net_name
            break

    else:
        # if none exists, raise
        raise NetworkInterfaceNotFound(f"There's no matching NIC with names {net_names}")

    for address in address_dict[matching_name]:
        types[address.family.name].append(address.address)

    return matching_name, types[AF_LINK.name][0], types[AF_INET.name], types[AF_INET6.name]
    # otherwise, no matching NIC


# ---

if __name__ == '__main__':
    name_, mac, ipv4, ipv6 = determine_current_nic("이더넷", "Wi-Fi", "Bluetooth 네트워크 연결")
    print(name_, mac, ipv4, ipv6)

Example Output:

Wi-Fi **-**-**-**-**-** ['___.___.___.___'] ['____::____:____:____:____']


Answered By - jupiterbjy
Answer Checked By - Cary Denson (WPSolving Admin)