Perdí mi teléfono en la oficina y pasé 50 minutos revolviendo todo el lugar buscándolo. La función “Encontrar” estaba desactivada por el sistema MDM de la empresa.
Sin más ideas, le pregunté a una Inteligencia Artificial cómo podía encontrarlo. Me sugirió rastrear la intensidad de la señal Bluetooth (RSSI) y, en cuestión de segundos, me generó un script en Python para medir la potencia en tiempo real.
Caminé por la oficina observando cómo aumentaba el número en la terminal… y lo encontré.
Al parecer, ahora simplemente puedes crear la herramienta que necesitas en el momento preciso. A continuación, te comparto la guía completa paso a paso para crear tu propio Radar Bluetooth Multidispositivo en macOS.
1. Crear un entorno virtual aislado (env) en macOS
Para evitar conflictos de librerías en tu sistema global, crearemos un entorno virtual que descargará todo lo necesario únicamente dentro de la carpeta de este proyecto.
Abre la Terminal de tu Mac, ve a la carpeta de tu proyecto y ejecuta:
|
1 2 3 4 5 6 |
# 1. Crear el entorno virtual llamado 'env' python3 -m venv env # 2. Activar el entorno virtual source env/bin/activate |
Nota: Una vez activado, verás el prefijo (env) al inicio de la línea de comandos de tu terminal.
2. Instalar las dependencias
Con el entorno activo (env), instala la librería bleak, que permite manejar la pila Bluetooth de macOS de forma asíncrona:
|
1 2 |
pip install bleak |
3. El Código: Radar Bluetooth Multidispositivo (TOP 20)
Crea un archivo llamado radar_top20.py dentro de la misma carpeta y pega el siguiente código en Python:
|
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 |
import asyncio import os import sys import time from bleak import BleakScanner # Almacena los dispositivos: { address: (rssi, nombre, timestamp_ultima_deteccion) } dispositivos_cercanos = {} def limpiar_dispositivos_viejos(timeout_segundos=4.0): """Elimina de la lista los dispositivos que dejaron de emitir señal.""" ahora = time.time() para_borrar = [ addr for addr, (_, _, t) in dispositivos_cercanos.items() if ahora - t > timeout_segundos ] for addr in para_borrar: del dispositivos_cercanos[addr] def renderizar_tabla(): """Limpia la consola y muestra los 20 dispositivos con mejor señal.""" limpiar_dispositivos_viejos() # Ordenar dispositivos por RSSI descendente (los más cercanos primero) ordenados = sorted( dispositivos_cercanos.items(), key=lambda item: item[1][0], reverse=True )[:20] # Limpiar pantalla de la terminal en macOS / Linux sys.stdout.write("\033[H\033[J") # Encabezado print("=" * 80) print(" 📡 RADAR BLUETOOTH MULTIDISPOSITIVO (TOP 20 MÁS CERCANOS)") print("=" * 80) print(f" Total detectados activos: {len(dispositivos_cercanos)} | Presiona Ctrl+C para salir") print("-" * 80) print(f"{'POS':<4} {'NOMBRE / IDENTIFICADOR':<30} {'RSSI':<8} {'PROXIMIDAD':<24} {'BARRA'}") print("-" * 80) if not ordenados: print("\n 🔎 Escaneando el entorno en busca de señales Bluetooth...\n") sys.stdout.flush() return for i, (addr, (rssi, nombre, _)) in enumerate(ordenados, 1): # Mapear el RSSI (-100 dBm a -30 dBm) a una barra de 15 bloques intensidad = max(0, min(15, int((rssi + 100) * (15 / 70)))) barra = "█" * intensidad + "░" * (15 - intensidad) # Estado visual if rssi > -50: estado = "🔥 ¡AL LADO!" elif rssi > -70: estado = "🙂 Cerca" elif rssi > -85: estado = "🥶 Lejos" else: estado = "📉 Muy lejos" # Formatear el nombre si es muy largo nombre_str = (nombre[:27] + "...") if len(nombre) > 30 else nombre print(f"#{i:<3} {nombre_str:<30} {rssi:4d} dBm {estado:<24} [{barra}]") print("-" * 80) sys.stdout.flush() async def main(): def callback(device, advertising_data): nombre = device.name or advertising_data.local_name or f"Dispositivo ({device.address[-6:]})" dispositivos_cercanos[device.address] = ( advertising_data.rssi, nombre, time.time() ) scanner = BleakScanner(detection_callback=callback) await scanner.start() try: while True: renderizar_tabla() await asyncio.sleep(0.3) # Actualiza la pantalla ~3 veces por segundo except asyncio.CancelledError: pass finally: await scanner.stop() print("\nEscaneo finalizado.") if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: print("\n\nSaliendo del radar...") |
4. Ejecución del Radar
Con tu entorno virtual activo en la terminal, ejecuta el script con el siguiente comando:
|
1 2 |
python3 radar_top20.py |
Nota importante para macOS: La primera vez que ejecutes el programa, macOS te pedirá permisos de Privacidad para que la Terminal pueda acceder a las funciones de Bluetooth. Haz clic en Permitir.
¿Cómo interpretar los datos del radar?
El valor RSSI mide la potencia de la señal de radio en decibelios (dBm) mediante números negativos:
- De -30 a -50 dBm (🔥 ¡AL LADO!): El dispositivo está a menos de 1 metro o sobre la misma mesa.
- De -50 a -70 dBm (🙂 Cerca): En la misma habitación, a unos pocos metros.
- De -70 a -85 dBm (🥶 Lejos): Cubierto por un objeto, en otra habitación o detrás de una pared.
- Menor a -85 dBm (📉 Muy lejos): En el límite de cobertura.
A medida que camines con tu ordenador portátil, la pantalla borrará y volverá a pintar la tabla 3 veces por segundo, mostrando dinámicamente arriba del todo el dispositivo que tengas más pegado en ese preciso instante.
Cuando hayas terminado de usarlo, puedes desactivar el entorno virtual escribiendo en la terminal:
|
1 |
deactivate |

