Detecção de presença do Raspberry Pi usando Wi-Fi


12

Como o Raspberry Pi pode procurar continuamente um endereço MAC na minha rede e executar uma tarefa quando ele detecta um endereço MAC específico?

Eu uso o meu Pi para executar várias tarefas de automação residencial. Gostaria que ele executasse uma tarefa quando sentir que meu telefone está conectado ao Wi-Fi (o que significa que acabei de chegar em casa). Qual é a melhor maneira de o Pi procurar continuamente o endereço MAC do meu telefone? Sei que posso usar arp-scana verificação de endereços MAC, mas preciso que esta seja verificada continuamente. Tenho certeza de que existe um método melhor do que arp-scanexecutar em loop ou usar cron para executá-lo a cada minuto.


2
Se você não precisa de resposta em tempo real, o cron é o melhor caminho. Primeiro você escreve um script que retorna algo como verdadeiro ou falso em sh (código de status é a melhor opção para privar resposta) e depois um script que armazena o valor anterior em algum lugar para / tmp e verifica se há alterações. Se alguma mudança acontecer, ela será registrada.
Misaz 30/05

Respostas:


3

Telefone de casa

Meu telefone funciona de maneira diferente, pois todos os telefones têm alguma diferença. Uma resposta de ping ocorre apenas se o telefone estiver ativado. Se o Pi for reinicializado e o telefone estiver no modo de suspensão, vários pings colocarão seus endereços IP e Mac na tabela arp, com 100% de perda de pacotes. Acabei de saber que o arpcomando é obsoleto, ip neighboré usado agora.

pi@RPi0:~ $ ip neighbor
169.254.65.43 dev eth0 lladdr 64:31:00:00:00:00 REACHABLE
192.168.0.1 dev wlan0 lladdr ac:b3:00:00:00:00 STALE
fe80::aeb3:13ff:fe00:000 dev wlan0 lladdr ac:b3:00:00:00:00 router STALE

pi@RPi0:~ $ ping 192.168.0.22
PING 192.168.0.22 (192.168.0.22) 56(84) bytes of data.
From 192.168.0.10 icmp_seq=1 Destination Host Unreachable
From 192.168.0.10 icmp_seq=2 Destination Host Unreachable
From 192.168.0.10 icmp_seq=3 Destination Host Unreachable
--- 192.168.0.22 ping statistics ---
34 packets transmitted, 0 received, +3 errors, 100% packet loss, time 34303ms

pi@RPi0:~ $ ip neighbor
192.168.0.1 dev wlan0 lladdr ac:b3:00:00:00:00 REACHABLE
169.254.65.43 dev eth0 lladdr 64:31:00:00:00:00 REACHABLE
192.168.0.22 dev wlan0 lladdr ac:37:00:00:00:00 REACHABLE
fe80::aeb3:13ff:fe00:000 dev wlan0 lladdr ac:b3:00:00:00:00 router STALE

Após o teste, minha solução seria ter dois loops dentro de um loop para sempre. o primeiro loop interno seria fazer um ping em vários endereços IP, várias vezes, o que seria possível para o meu telefone. Meu roteador reservou o primeiro endereço IP 19 e eu posso ter cerca de meia dúzia de endereços que o DHCP atribuirá, incluindo meu telefone, começando no endereço 192.168.0.20. Vou executar ping em uma dúzia de endereços IP uma vez, no modo de segundo plano, esperar um segundo pela resposta e jogar os resultados fora como lixo. Vou esperar oito segundos na tabela arp e executarei o ip neighborcomando grep o endereço mac para o endereço IP. O roteador e o telefone manterão esse mesmo endereço IP, a menos que algo incomum aconteça. A tabela arp permanecerá no Pi, mas vai mudar estados de REACHABLE, STALEe FAILEDde pings e tempo.

O segundo loop interno fará ping e verificará a tabela arp a cada cinco minutos para determinar se o telefone está em casa. Com três ping 'FAILED' seguidos, o telefone não está em casa. Um 'ACESSÍVEL', quando o telefone não está em casa, fará com que o telefone volte para casa (faça alguma coisa). Existem verificações para validar o endereço IP e retornar ao primeiro loop interno, se forem necessárias correções.

#!/bin/bash
# A script to do something when Phone returns Home.

mac="ac:37:00:00:00:00"    # Your phone mac address
ip_addr=""                 # Leave blank or ip for test
network="192.168.0.0"      # Your network (Class C only)
range="20 32"              # ip address possible range
pgm='echo "do something"'  # program to exec when Phone returns Home

start=$(echo "$range" | cut -d " " -f1)
stop=$(echo "$range" | cut -d " " -f2)
network=$(echo "$network" | cut -d. -f1-3)

echo "Start  $(date)"
while [ 1 ]; do
    cnt=0
    fail=0
    [ "$ip_addr" ] || while [ ! "$ip_addr" ]; do
        for x in $(seq "$start" "$stop"); do
            (junk=$(ping -c1 -W1 "$network"."$x") & )
            wait
        done
        sleep 8
        ip_addr=$(ip neighbor | grep "$mac" | cut -d " " -f1)
        ((cnt++))
        if (( $cnt > 15 )); then
            cnt=0
            echo "--- Phone not Home  $(date)"
            sleep 300      # 5 minutes
        fi
        if [ "$ip_addr" ]; then
            echo "--- Phone is Home, Count = $cnt, Date = $(date)"
            echo "Phone ip = $ip_addr  mac = $mac"
        fi
    done

    while [ "$ip_addr" ]; do
        junk="$(ping -c1 -W1 $ip_addr)"
        sleep 8
        home_nw="$(ip neighbor | grep $ip_addr | cut -d ' ' -f 1,5,6)"
        echo "$home_nw - $(date)"
        is_home=$(echo "$home_nw" | cut -d " " -f3)
        if [ "$is_home" == "REACHABLE" ] && (( "$fail" >= 3 )); then
            echo "--- Phone returned Home - $(date)"
            $pgm
        fi
        [ "$is_home" == "REACHABLE" ] && fail=0
        mac_stat=$(echo "$home_nw" | cut -d " " -f2)
        if [ "$mac_stat" == "FAILED" ]; then
            (( "$fail" < 10 )) && ((fail++))
            ip_test="$(ip neighbor | grep $mac | cut -d ' ' -f1)"
            if [ "$ip_test" ]; then
                [ "$ip_test" == "$ip_addr" ] || ip_addr=""
            fi
            if (( "$fail" == 3 )); then
                echo "--- Phone not at Home  $(date)"
            fi
        else
            if [ "$mac_stat" != "$mac" ]; then
                ip_addr=""
            fi
        fi
        sleep 300          # 5 minutes
    done
done

3

Por que não adicionar uma reserva ao endereço IP do seu telefone / es e simplesmente executar um ping através de um trabalho cron a cada poucos minutos.

    #!/bin/bash
    HOSTS="x.x.x.1 x.x.x.2"
    COUNT=10
    for myHost in $HOSTS
    do
      count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
      if [ $count -eq 10 ]; then
        # 100% response
        # let the cat out
      fi
    done

Eu faço isso no meu rpi usando o fhem , ele possui um módulo de detecção de presença integrado que permite definir status de residente que pode ser consultado para influenciar as tarefas de automação residencial.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.