Détection de présence Raspberry Pi via Wi-Fi

12

Comment puis-je faire en sorte que mon Raspberry Pi recherche continuellement une adresse MAC sur mon réseau, puis effectue une tâche lorsqu'il détecte une adresse MAC spécifique?

J'utilise mon Pi pour exécuter diverses tâches domotiques. Je voudrais qu'il exécute une tâche lorsqu'il détecte que mon téléphone se connecte au Wi-Fi (ce qui signifie que je viens de rentrer à la maison). Quelle est la meilleure façon d'avoir le scan Pi pour l'adresse MAC de mon téléphone en continu? Je sais que je peux utiliser arp-scanpour rechercher des adresses MAC, mais j'en ai besoin pour rechercher en permanence. Je suis sûr qu'il y a une meilleure méthode que d'avoir arp-scanexécuté en boucle, ou d'utiliser cron pour l'exécuter toutes les minutes.

gsears
la source
2
Si vous n'avez pas besoin d'une réponse en temps réel, cron est le meilleur moyen. D'abord, vous écrivez un script qui retourne quelque chose comme vrai ou faux dans sh (le code d'état est la meilleure option pour une réponse privée) puis un script qui stockera la valeur précédente quelque part dans / tmp et vérifiera le changement. Si le changement survient, il l'enregistrera.
Misaz

Réponses:

3

PhoneHome

Mon téléphone agit différemment, car tous les téléphones ont une différence. Une réponse ping ne se produit que si le téléphone est réveillé. Si le Pi est redémarré et que le téléphone est en mode veille, plusieurs pings placeront ses adresses ip et mac dans la table arp, avec une perte de paquets de 100%. Je viens d'apprendre que la arpcommande est obsolète, ip neighborest utilisée maintenant.

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

Après le test, ma solution serait d'avoir deux boucles à l'intérieur d'une boucle pour toujours. la première boucle intérieure serait de faire un ping sur une plage d'adresses IP, plusieurs fois, ce serait possible pour mon téléphone. Mon routeur a réservé la première 19 adresses IP et j'ai peut-être une demi-douzaine d'adresses que DHCP attribuera, y compris mon téléphone, à partir de l'adresse 192.168.0.20. Je vais pinguer une douzaine d'adresses IP une fois, en mode arrière-plan, attendre une seconde pour la réponse et jeter les résultats comme indésirables. Je vais attendre huit secondes sur la table arp et exécuter la ip neighborcommande, grep l'adresse mac pour l'adresse ip. Le routeur et le téléphone conserveront cette même adresse IP, sauf si quelque chose d'inhabituel se produit. Le tableau arp restera dans la Pi, mais changera d' état à partir REACHABLE, STALEet FAILEDde pings et de temps.

La deuxième boucle intérieure va cingler et vérifier la table d'arp toutes les cinq minutes pour déterminer si le téléphone est à la maison. Avec trois ping «FAILED» d'affilée, le téléphone n'est pas à la maison. Un «REACHABLE», lorsque le téléphone n'est pas à la maison, fera revenir le téléphone à la maison (faire quelque chose). Il y a des vérifications pour valider l'adresse IP et revenir à la première boucle intérieure si des corrections sont nécessaires.

#!/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
bstipe
la source
3

Pourquoi ne pas ajouter une réservation à l'adresse IP de votre téléphone et faire simplement un ping via un travail cron toutes les quelques minutes.

    #!/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

J'accomplis cela sur mon rpi en utilisant fhem , il a un module de détection de présence intégré qui me permet de définir des statuts de résident qui peuvent être interrogés pour influencer les tâches domotiques.

paj
la source