¿Detectar si hay un iPhone / Android cerca?

10

Estoy trabajando remotamente y sería útil saber cuándo alguien ha salido a una reunión / almuerzo en mi oficina.

Pensé que podría detectar pasivamente qué teléfonos cerca de la frambuesa pi (y luego publicarlos en la web / dropbox / lo que sea)

¿Cuál sería la forma más fácil de hacer esto? Detección de dirección MAC? ¿Bluetooth?

ACooleman
fuente

Respuestas:

10

Mucha caza, aprendí bastante, no hubo suerte al detectar dispositivos de otras personas sin mucho escaneo inalámbrico de bajo nivel: Bluetooth funciona para iPhone si ambos son sus propios dispositivos:

  1. El escaneo Wifi puede funcionar para algunos dispositivos, ¡pero los iOS no se conectan cuando la pantalla está apagada! Mi iPhone 6 podría detectarse con un arpcomando simple (proporciona una tabla de números de IP y Mac de dispositivos conectados en la misma subred), pero esto solo sucedería cuando la pantalla del teléfono esté iluminada. Una vez que la pantalla del teléfono duerme, ¡está fuera de los límites en wifi! Apuesto a que esto es en interés de la duración de la batería.

  2. El dongle Bluetooth funcionó. No hay cálculo de distancia a diferencia de algunos algoritmos sofisticados: solo presente / ausente se puede hacer con muy poco consumo de energía en rPi y iPhone. Instale el dongle bluetooth en rPi como: ( sudo aptitude install bluetooth bluez-utils bluez-compat). Averigüe la mac de su dispositivo telefónico haciendo que se pueda buscar y luego haga ( hcitool scan) en rPi. Luego, conéctese a su dispositivo (asegúrese de que se pueda buscar) como: sudo bluez-simple-agent hci0 mac_of_your_devicey diga sí en ambos lados. Entonces sudo bluez-test-device trusted mac_of_your_device. Ahora los dos se "conocen". Entonces hazlosudo hcitool name mac_of_your_deviceen tu script favorito para averiguar si el iPhone está cerca. Esto no creará una conexión, pero solo dile hola. Si devuelve un nombre, el teléfono está cerca. Si no devuelve nada, el teléfono no está cerca o el bluetooth está apagado. En comparación con la creación de conexiones u otros métodos de cálculo de distancia, este método conserva la batería en ambos lados y mantiene la contaminación de las ondas de aire al mínimo.

Ravi Tejwani
fuente
9

Yo y algunos amigos míos he estado desarrollando un escáner bluetooth-proximidad a abrir la cerradura de la puerta principal de nuestra hackerspace .

Hemos emparejado todos los dispositivos permitidos y esencialmente los hemos utilizado hcitoolpara probar si uno de los dispositivos emparejados está cerca. Como ejemplo, si el dispositivo emparejado tiene la dirección "00: 00: 00: 00: 00: 00", lo haría en la consola de línea de comandos:

hcitool cc 00:00:00:00:00:00 && hcitool auth 00:00:00:00:00:00 && hcitool dc 00:00:00:00:00:00;

Si esto devuelve cero, el dispositivo está cerca.

Una desventaja es que esto tomará ~ 5 segundos para el tiempo de espera si el dispositivo no está cerca.

Hemos publicado el código fuente en Github bajo la licencia de código abierto de apache.

MadMike
fuente
2
Puedo confirmar que esto funciona usando hcitool .... Sin embargo, debe encadenar los comandos como en el ejemplo anterior. La conexión solo está activa durante un período de tiempo muy corto. Puede agregar proximidad a la mezcla haciendo hcitool rssi ....
Gunnar
2

He visto algunas configuraciones que usan bluetooth para casos de uso similares, pero probablemente implicará algún pirateo. Los teléfonos que desea detectar generalmente no están en modo reconocible.

Si los teléfonos usan wifi, probablemente pueda detectar cierta proximidad, pero esto probablemente también significará que tendrá que buscarlos en una capa bastante baja, ya que no accederán a su antena wifi y probablemente se conectarán encriptados. Eche un vistazo a kismet para obtener una bonanza inalámbrica de bajo nivel.

Sin embargo, supongo que la forma más fácil de detectar si alguien está en una habitación o no es utilizar el módulo de la cámara y un espejo panorámico.

Bex
fuente
1

Si tiene una red WiFi a la que se conectan cuando están en la oficina, puede hacer que el PI busque direcciones MAC cada x períodos de tiempo y actualice una página web (dropbox, lo que sea) con el estado actual. Probablemente la ruta más confiable.

Es posible que pueda hacer algo con bluetooth y un adaptador USB Bluetooth, pero no tengo experiencia con eso.

Sin ellos conectados a la pi, o la red en la que está conectada la pi, no creo que tenga mucho éxito.

Mantequillas
fuente
Agradable. Entonces, ¿qué tecnología / aplicación / plataforma estaba pensando que usaría para escanear las direcciones MAC?
ACooleman
La forma en que lo haría es con nmap, la versión de línea de comando y un pequeño código personalizado de Python (estoy seguro de que hay una API Python), hacer una consulta rápida de barrido de ping / MAC, comparar eso con una lista preconstruida, use eso para construir una página php (HTML?) y servirla usando el servidor web lightppd (Apache?). Configure el trabajo de Python para que se ejecute cada x período de tiempo y haga que la página web se actualice automáticamente cada período. Es una buena idea de proyecto ... Tal vez tenga que intentarlo después de terminar todos los otros proyectos que están en mi plato.
Butters
Es posible que pueda consultar su enrutador para la tabla ARP, o también su servidor DHCP ... Podría hacerlo un poco más rápido ...
Butters
1

Leer las respuestas anteriores también me llevó a pensar en la siguiente posibilidad:

use airmon-ng para escanear continuamente la red en busca de dispositivos cliente en wifi. La salida se puede escribir en un archivo, por lo que si el archivo cambia, un cliente ha ingresado o ha salido del rango de pi. Tener una lista de direcciones mac conocidas le permite identificar al usuario y, debido al cambio de archivo, podría desencadenar algunas acciones ...

¡Es una idea bastante interesante! ¡Gracias!

Arjen

credmp
fuente
Las grandes tiendas utilizan esta técnica para controlar cómo los compradores navegan por sus productos, qué rayón se saltan, etc. Pero debido a las leyes de privacidad no siempre es legal vincular una dirección MAC a una persona en cada país.
Havnar
1

Así que he estado trabajando en el mismo tema durante aproximadamente un año. Lo hice funcionar en mi Mac con bastante rapidez, pero tuve muchos problemas para que funcione correctamente en mi PC. He intentado muchos enfoques diferentes. Tengo un sistema de automatización del hogar que enciende la calefacción y el agua caliente (a través de un módulo arduino y RF) cuando yo o mi compañero estamos en casa (es decir, nuestros iPhones son detectables en el WiFi de la casa). Al final, utilicé 'nslookup' para encontrar la dirección IP de los iPhone (en caso de que la dirección IP haya cambiado ya que son dinámicos (pero en realidad nunca lo hacen en mi enrutador)) y 'nmap' para detectar si el iPhone está encendido la red Si el iPhone está en reposo profundo, 'nmap' no siempre encuentra el teléfono, por lo que lo he comprobado 10 veces antes de que diga que el teléfono no está en casa. A continuación se muestra parte de mi código de automatización del hogar en Python. He usado hilos. Cualquier pregunta con el siguiente código, hágamelo saber.

# Dictionary to store variables to reuse on program restart
    v = {
        'boilerControlCH' : 'HIH', # 'scheduled' or 'HIH' (Honey I'm Home)
        'boilerControlHW' : 'scheduled',
        'thermostatSetPoint' : 20.8,
        'thermostatVariance' : 0.1,
        'morningTime' : datetime(1970,1,1,6,0,0),
        'nightTime' : datetime(1970,1,1,23,0,0),
        'someOneHome' : False,
        'guest' : False,
        'minimumTemperatureOO' : False,
        'minimumTemperature' : 4.0,
        'iPhoneMark' : {'iPhoneHostname' : 'marks-iphone', 'home' : False},
        'iPhoneJessica' : {'iPhoneHostname' :'jessicaesiphone', 'home' : False}
        }

y

# Check if anyone at home
    def occupancyStatus(person, Bol = False):
        with lockOccupancyStatus:
            someOneHome = False

        if 'iPhone' in person:
            v[person]['home'] = Bol
        elif 'retest' in person:
            pass
        else:
            v[person] = Bol

        if v['guest'] == True:
            someOneHome = True

        for key in v:
            if 'iPhone' in key:
                if v[key]['home'] == True:
                    someOneHome = True

        v['someOneHome'] = someOneHome
        variablesToFile()
    return

y el código principal

   # iPhone home status threading code
    class nmapClass(threading.Thread):
        def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        global exitCounter

        nmapThread()
        msg.log('Exited nmapThread')    
        waitEvent.set()
        waitEventAdjustable.set()
        serialDataWaiting.set()
        exitCounter += 1


def nmapThread():
    iPhone = {}
    maxCounts = 10
    for phone in v:
        if 'iPhone' in phone:
            iPhone[phone] = {}
            iPhone[phone]['hostname'] = v[phone]['iPhoneHostname']
            iPhone[phone]['count'] = maxCounts
    #msg.log(iPhone)

    while exitFlag[0] == 0:
        for phone in iPhone:
            if iPhone[phone]['count'] > 0:
                phoneFound = False
                IPAddress = '0.0.0.0'

                # Find iPhones IP address using its hostname
                commandNsloolup = 'nslookup %s' %iPhone[phone]['hostname']
                childNslookup = pexpect.popen_spawn.PopenSpawn(commandNsloolup, timeout = None)
                output = childNslookup.readline()
                while '\r\n' in output:
                    #msg.log(output)
                    if 'Name:' in output:
                        output = childNslookup.readline()
                        if 'Address:' in output:
                            tempStr = output
                            startPoint = tempStr.find('192')
                            tempStr = tempStr[startPoint:]
                            IPAddress = tempStr.replace('\r\n', '')
                            #msg.log(IPAddress)
                    output = childNslookup.readline()


                if IPAddress == '0.0.0.0':
                    pass
                    #msg.error('Error finding IP address for %s' %iPhone[phone]['hostname'], GFI(CF()).lineno)
                else:
                    #commandNmap = 'nmap -PR -sn %s' %IPAddress
                    #commandNmap = 'nmap -p 62078 -Pn %s' %IPAddress # -p specifies ports to try and access, -Pn removes pinging
                    commandNmap = 'nmap -p 62078 --max-rate 100 %s' %IPAddress
                    childNmap = pexpect.popen_spawn.PopenSpawn(commandNmap, timeout = None)
                    output = childNmap.readline()
                    while '\r\n' in output:
                        if 'Host is up' in output:
                            phoneFound = True
                            break
                        output = childNmap.readline()
                    #if phoneFound:
                    #   break


                if phoneFound:              
                    iPhone[phone]['count'] = 0

                    if v[phone]['home'] == False:
                        msg.log('%s\'s iPhone has returned home' %phone)
                        occupancyStatus(phone, True)
                        waitEventAdjustable.set()
                    #else:
                        #msg.log('%s\'s iPhone still at home' %phone)
                else:
                    iPhone[phone]['count'] -= 1

                    if v[phone]['home'] == True and iPhone[phone]['count'] == 0:
                        msg.log('%s\'s iPhone has left home' %phone)
                        occupancyStatus(phone, False)
                        waitEventAdjustable.set()
                    #else:
                        #msg.log('%s\'s iPhone still away from home' %phone)

            elif iPhone[phone]['count'] < 0:
                msg.error('Error with count variable in iPhone dictionary', GFI(CF()).lineno)


        longWait = True
        for phone in iPhone:
            if iPhone[phone]['count'] > 0:
                longWait = False
                #msg.log('%s: %s' %(phone, iPhone[phone]['count']))

        if longWait:
            #msg.log('wait long')               
            # 600 = run every 10 minutes
            waitEvent.wait(timeout=600)
            for phone in iPhone:
                iPhone[phone]['count'] = maxCounts
        else:
            #msg.log('wait short')
            waitEvent.wait(timeout=60)  

    return

Es posible que el código no funcione si lo copia directamente en su propio script, ya que faltan algunas partes que no he copiado para tratar de mantener las cosas simples y fáciles de leer, pero espero que el código anterior les dé a todos una idea de cómo lo hice cosas.

irishcream24
fuente