#!/usr/bin/env python # allowed fields: NAME,SSID,SSID-HEX,BSSID,MODE,CHAN,FREQ,RATE,BANDWIDTH,SIGNAL,BARS,SECURITY,WPA-FLAGS,RSN-FLAGS,DEVICE,ACTIVE,IN-USE,DBUS-PATH # TODO: can't connect to AP with empty ssid import subprocess as sp import sys CFG = { "nmcli": { #"device": "", "fields": ["ssid", "signal", "security", "chan", "rate", "mode", "bssid"], }, "rfkill": { "device": "wlan" } } if not CFG["nmcli"]["fields"][0].lower() == "ssid": raise NotImplementedError("ssid must be the first element in fields, will hopefully be fixed in the future") def _split_blocks(text: str) -> list: lines_list = text.splitlines() field_len = len(CFG["nmcli"]["fields"]) if len(lines_list) % field_len: raise ValueError("The amount of field elements doesn't devide evenly by the number of fields") return [ lines_list[i:i+field_len] for i in range(0, len(lines_list), field_len) ] def _parse_blocks(block_list: list) -> list: new_block_list = [] for block in block_list: block_dict = {} for element in block: elm_split = element.split(":", 1) block_dict[elm_split[0]] = elm_split[1] new_block_list.append(block_dict) return new_block_list def _gather_wifi() -> str: sp.run(["nmcli", "dev", "wifi", "rescan"]) wifi_text = sp.run( [ "nmcli", "--terse", "--colors", "no", "--escape", "yes", "--mode", "multiline", "--fields", ",".join(CFG["nmcli"]["fields"]), "dev", "wifi" ], capture_output=True, text=True ) return wifi_text.stdout def query_ssid(ssid: str) -> list: gathered_connections = [] for element in get_wifi(): if element["SSID"] == ssid: gathered_connections.append(element) return gathered_connections def get_wifi() -> list: return _parse_blocks(_split_blocks(_gather_wifi())) def connect(ssid: str) -> bool: gathered_connections = query_ssid(ssid) if len(gathered_connections) == 0: print("Found no matching wifi ssid") return False # think about the return type later #connect_cmd = ["nmcli", "connection", "up", "id", ssid, "iface", "wifi"] connection_id = ssid if len(gathered_connections) > 1: print("Found multiple access points with the exact same name (ssid)") print("bssid:") for element in gathered_connections: print(" " * 4 + element["BSSID"], element["SIGNAL"] + "%") answer = input("Do you want to choose a specific BSSID? [y/N]: ").lower() if answer == "y": connection_id = input("Which bssid: ") sp.run(["rfkill", "unblock", CFG["rfkill"]["device"]]) sp.run(["nmcli", "networking", "on"]) connect_cmd = ["nmcli", "--ask", "device", "wifi", "connect", connection_id] sp.run(connect_cmd) return True def main(): try: my_dict = get_wifi() for element in my_dict: print(element) my_input = input("wifi_name: ") connect(my_input) except KeyboardInterrupt: print("") print(">>> Interrupted by user") sys.exit(1) if __name__ == "__main__": main()