PhoneHome
Il mio telefono funziona in modo diverso, poiché tutti i telefoni hanno qualche differenza. Una risposta al ping si verifica solo se il telefono è attivo. Se il Pi viene riavviato e il telefono è in modalità sospensione, più ping inseriranno i suoi indirizzi ip e mac nella tabella arp, con una perdita di pacchetti del 100%. Ho appena imparato che il arp
comando è obsoleto, ip neighbor
viene utilizzato ora.
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
Dopo il test, la mia soluzione sarebbe quella di avere due loop all'interno di un loop per sempre. il primo ciclo interno sarebbe quello di fare un ping su un intervallo di indirizzi IP, più volte, che sarebbe possibile per il mio telefono. Il mio router ha riservato il primo indirizzo IP 19 e potrei avere una mezza dozzina di indirizzi che DHCP assegnerà, incluso il mio telefono, a partire dall'indirizzo 192.168.0.20. Eseguirò il ping di una dozzina di indirizzi IP una volta, in modalità background, aspetterò un secondo per la risposta e getterò via i risultati come spazzatura. Aspetterò otto secondi sulla tabella arp ed eseguirò il ip neighbor
comando, grep l'indirizzo mac per l'indirizzo IP. Il router e il telefono manterranno lo stesso indirizzo IP a meno che non accada qualcosa di insolito. La tabella ARP rimarrà nel Pi, ma cambierà stati da REACHABLE
, STALE
e FAILED
da ping e tempo.
Il secondo ciclo interno eseguirà il ping e controllerà la tabella ARP ogni cinque minuti per determinare se il telefono è a casa. Con tre ping "FAILED" di seguito, il telefono non è in casa. Un 'REACHABLE', quando il telefono non è in casa, farà tornare il telefono a casa (fare qualcosa). Ci sono controlli per convalidare l'indirizzo IP e tornare al primo ciclo interno se sono necessarie correzioni.
#!/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