El cálculo de la distancia es una estimación.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
import subprocess import re from prettytable import PrettyTable def calculate_distance(signal_dBm): """ Calcula la distancia estimada en metros basándose en la potencia de la señal en dBm. """ C = 40 # Parámetro de ajuste, que puede variar según el entorno try: # Extraer el primer valor de señal si hay más de uno signal_dBm_value = float(signal_dBm.split(' / ')[0].replace(' dBm', '').strip()) # La fórmula para calcular la distancia en metros distance = 10 ** ((-signal_dBm_value - C) / 20.0) return distance except ValueError: return float('inf') # Si no se puede calcular, retorna infinito def get_wifi_info(): try: # Ejecutar el comando system_profiler command = ['system_profiler', 'SPAirPortDataType'] result = subprocess.check_output(command, universal_newlines=True) # Usar una expresión regular para encontrar la sección de "Other Local Wi-Fi Networks" match = re.search(r'Other Local Wi-Fi Networks:\n((?:\s+.+\n)+)', result) if match: # Extraer la sección de interés other_networks_section = match.group(1).strip() # Eliminar secciones que empiezan con 'awdl0:' filtered_lines = [] skip_block = False for line in other_networks_section.splitlines(): if line.strip().startswith("awdl0:"): skip_block = True if not skip_block: filtered_lines.append(line) if line.strip() == "": skip_block = False # Unir las líneas filtradas en una sola cadena filtered_section = "\n".join(filtered_lines).strip() # Expresión regular para extraer los datos de la red network_info_re = re.compile( r'(?P<SSID>[^\:]+):\s*PHY Mode:\s*(?P<mode>\S+)\s*' r'Channel:\s*(?P<channel>[^\n]+)\s*' r'(?:Country Code:\s*(?P<country_code>[^\n]+)\s*)?' r'Network Type:\s*(?P<network_type>[^\n]+)\s*' r'Security:\s*(?P<security>[^\n]+)\s*' r'Signal / Noise:\s*(?P<signal>[^\n]+)\s*' r'(?:Transmit Rate:\s*(?P<transmit_rate>[^\n]+)\s*)?' r'(?:MCS Index:\s*(?P<mcs>[^\n]+)\s*)?' ) # Crear una tabla para mostrar los datos table = PrettyTable() table.field_names = ["Nombre WiFi", "PHY Mode", "Channel", "Country Code", "Network Type", "Security", "Signal", "Transmit Rate", "MCS Index", "Distance (meters)"] # Buscar todas las redes en la sección extraída rows = [] for match in network_info_re.finditer(filtered_section): ssid = match.group('SSID').strip() mode = match.group('mode').strip() channel = match.group('channel').strip() country_code = match.group('country_code').strip() if match.group('country_code') else "N/A" network_type = match.group('network_type').strip() security = match.group('security').strip() signal = match.group('signal').strip() transmit_rate = match.group('transmit_rate').strip() if match.group('transmit_rate') else "N/A" mcs = match.group('mcs').strip() if match.group('mcs') else "N/A" # Calcular la distancia distance = calculate_distance(signal) # Agregar una fila a la lista rows.append([ssid, mode, channel, country_code, network_type, security, signal, transmit_rate, mcs, distance]) # Ordenar las filas por la distancia (de menor a mayor) rows.sort(key=lambda x: x[-1]) # Agregar las filas a la tabla for row in rows: table.add_row(row) # Imprimir la tabla print(table) else: print("No se encontró la sección de 'Other Local Wi-Fi Networks'.") except subprocess.CalledProcessError as e: print(f"Error al ejecutar el comando system_profiler: {e}") except Exception as e: print(f"Error inesperado: {e}") def main(): get_wifi_info() if __name__ == '__main__': main() |
Actualizar el script cada 3 segundo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
import subprocess import re import time from prettytable import PrettyTable def calculate_distance(signal_dBm): """ Calcula la distancia estimada en metros basándose en la potencia de la señal en dBm. """ C = 40 # Parámetro de ajuste, que puede variar según el entorno try: # Extraer el primer valor de señal si hay más de uno signal_dBm_value = float(signal_dBm.split(' / ')[0].replace(' dBm', '').strip()) # La fórmula para calcular la distancia en metros distance = 10 ** ((-signal_dBm_value - C) / 20.0) return distance except ValueError: return float('inf') # Si no se puede calcular, retorna infinito def get_wifi_info(): try: # Ejecutar el comando system_profiler command = ['system_profiler', 'SPAirPortDataType'] result = subprocess.check_output(command, universal_newlines=True) # Usar una expresión regular para encontrar la sección de "Other Local Wi-Fi Networks" match = re.search(r'Other Local Wi-Fi Networks:\n((?:\s+.+\n)+)', result) if match: # Extraer la sección de interés other_networks_section = match.group(1).strip() # Eliminar secciones que empiezan con 'awdl0:' filtered_lines = [] skip_block = False for line in other_networks_section.splitlines(): if line.strip().startswith("awdl0:"): skip_block = True if not skip_block: filtered_lines.append(line) if line.strip() == "": skip_block = False # Unir las líneas filtradas en una sola cadena filtered_section = "\n".join(filtered_lines).strip() # Expresión regular para extraer los datos de la red network_info_re = re.compile( r'(?P<SSID>[^\:]+):\s*PHY Mode:\s*(?P<mode>\S+)\s*' r'Channel:\s*(?P<channel>[^\n]+)\s*' r'(?:Country Code:\s*(?P<country_code>[^\n]+)\s*)?' r'Network Type:\s*(?P<network_type>[^\n]+)\s*' r'Security:\s*(?P<security>[^\n]+)\s*' r'Signal / Noise:\s*(?P<signal>[^\n]+)\s*' r'(?:Transmit Rate:\s*(?P<transmit_rate>[^\n]+)\s*)?' r'(?:MCS Index:\s*(?P<mcs>[^\n]+)\s*)?' ) # Crear una tabla para mostrar los datos table = PrettyTable() table.field_names = ["Nombre WiFi", "PHY Mode", "Channel", "Country Code", "Network Type", "Security", "Signal", "Transmit Rate", "MCS Index", "Distance (meters)"] # Buscar todas las redes en la sección extraída rows = [] for match in network_info_re.finditer(filtered_section): ssid = match.group('SSID').strip() mode = match.group('mode').strip() channel = match.group('channel').strip() country_code = match.group('country_code').strip() if match.group('country_code') else "N/A" network_type = match.group('network_type').strip() security = match.group('security').strip() signal = match.group('signal').strip() transmit_rate = match.group('transmit_rate').strip() if match.group('transmit_rate') else "N/A" mcs = match.group('mcs').strip() if match.group('mcs') else "N/A" # Calcular la distancia distance = calculate_distance(signal) # Agregar una fila a la lista rows.append([ssid, mode, channel, country_code, network_type, security, signal, transmit_rate, mcs, distance]) # Ordenar las filas por la distancia (de menor a mayor) rows.sort(key=lambda x: x[-1]) # Limpiar la pantalla antes de imprimir la nueva tabla (opcional) print("\033c", end="") # Imprimir la tabla table.clear_rows() # Limpia las filas anteriores para evitar duplicados for row in rows: table.add_row(row) print(table) else: print("No se encontró la sección de 'Other Local Wi-Fi Networks'.") except subprocess.CalledProcessError as e: print(f"Error al ejecutar el comando system_profiler: {e}") except Exception as e: print(f"Error inesperado: {e}") def main(): while True: get_wifi_info() time.sleep(3) # Esperar 3 segundos antes de la próxima actualización if __name__ == '__main__': main() |