Teléfono de casa
Mi teléfono actúa de manera diferente, ya que todos los teléfonos tienen alguna diferencia. Una respuesta de ping solo ocurre si el teléfono está despierto. Si se reinicia el Pi y el teléfono está en modo de suspensión, múltiples pings colocarán sus direcciones IP y Mac en la tabla arp, con una pérdida de paquetes del 100%. Acabo de enterarme de que el arp
comando está obsoleto, ip neighbor
se usa ahora.
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
Después de la prueba, mi solución sería tener dos bucles dentro de un bucle para siempre. el primer bucle interno sería hacer un ping en un rango de direcciones IP, varias veces, que sería posible para mi teléfono. Mi enrutador ha reservado la primera dirección IP 19 y es posible que tenga aproximadamente media docena de direcciones que DHCP asignará, incluido mi teléfono, a partir de la dirección 192.168.0.20. Haré ping una docena de direcciones IP una vez, en modo de fondo, esperaré un segundo para recibir una respuesta y arrojaré los resultados como basura. Esperaré ocho segundos en la tabla arp, y ejecutaré el ip neighbor
comando, grep la dirección mac para la dirección ip. El enrutador y el teléfono mantendrán esta misma dirección IP a menos que ocurra algo inusual. La tabla ARP permanecerá en el Pi, pero va a cambiar los estados de REACHABLE
, STALE
y FAILED
desde hace ping y el tiempo.
El segundo bucle interno hará ping y verificará la tabla arp cada cinco minutos para determinar si el teléfono está en casa. Con tres ping 'FALLIDOS' seguidos, el teléfono no está en casa. Un 'REACHABLE', cuando el teléfono no está en casa, hará que el teléfono regrese a casa (haga algo). Hay verificaciones para validar la dirección IP y volver al primer bucle interno si se requieren correcciones.
#!/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