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 arp
commande est obsolète, ip neighbor
est 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 neighbor
commande, 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
, STALE
et FAILED
de 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