PhoneHome
Мій телефон діє по-різному, оскільки всі телефони мають певну різницю. Відповідь Ping відбувається лише в тому випадку, коли телефон прокинувся. Якщо Pi перезавантажиться і телефон перебуває у сплячому режимі, кілька пінгів розмістять свої ip та mac адреси в таблиці арп, зі 100% втратою пакетів. Я щойно дізнався, що arp
команда застаріла, і ip neighbor
зараз використовується.
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
Після тестування моїм рішенням було б мати дві петлі всередині вічної петлі. першим внутрішнім циклом було б зробити пінг по ряду ip-адрес, кілька разів, що було б можливо для мого телефону. Мій маршрутизатор зарезервував першу 19 ip адресу, і я можу мати півтора десятка адреси, які призначить DHCP, включаючи мій телефон, починаючи з адреси 192.168.0.20. Я напишу десяток ip-адреси один раз, у фоновому режимі, зачекаю одну секунду на відповідь і відкину результати як непотріб. Я зачекаю вісім секунд на таблиці arp і запускаю ip neighbor
команду, грептую мак-адресу для ip-адреси. Маршрутизатор і телефон зберігатимуть цю ж ip адресу, якщо щось незвичне не станеться. Таблиця агр залишатиметься в Pi, але змінить стану від REACHABLE
, STALE
і FAILED
від пінгів і часу.
Другий внутрішній цикл буде пінг і перевіряти таблицю арп кожні п'ять хвилин, щоб визначити, чи є телефон вдома. З трьома пінгами "FAILED" поспіль телефон не вдома. Один "ДОСТАВЧИЙ", коли телефону немає вдома, змусить телефон повернутися додому (щось зробити). Існують перевірки на підтвердження ip-адреси та повернення до першого внутрішнього циклу, якщо потрібні виправлення.
#!/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