Điện thoại
Điện thoại của tôi hoạt động khác nhau, vì tất cả các điện thoại có một số khác biệt. Phản hồi ping chỉ xảy ra nếu điện thoại còn thức. Nếu Pi được khởi động lại và điện thoại ở chế độ ngủ, nhiều ping sẽ đặt địa chỉ ip và mac của nó vào bảng arp, với việc mất gói 100%. Tôi mới biết rằng arp
lệnh đã lỗi thời, ip neighbor
được sử dụng ngay bây giờ.
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
Sau khi thử nghiệm, giải pháp của tôi là có hai vòng lặp bên trong một vòng lặp mãi mãi. vòng lặp bên trong đầu tiên sẽ thực hiện ping trên một loạt địa chỉ IP, nhiều lần, điều đó có thể thực hiện được cho điện thoại của tôi. Bộ định tuyến của tôi đã dành 19 địa chỉ IP đầu tiên và tôi có thể có khoảng nửa tá địa chỉ mà DHCP sẽ gán, bao gồm cả điện thoại của tôi, bắt đầu từ địa chỉ 192.168.0.20. Tôi sẽ ping một tá địa chỉ IP một lần, ở chế độ nền, đợi một giây để phản hồi và ném kết quả đi như rác. Tôi sẽ đợi tám giây trên bảng arp và chạy ip neighbor
lệnh, grep địa chỉ mac cho địa chỉ ip. Bộ định tuyến và điện thoại sẽ giữ cùng địa chỉ IP này trừ khi có điều gì đó bất thường xảy ra. Bảng arp sẽ vẫn trong Pi, nhưng sẽ thay đổi trạng thái từ REACHABLE
, STALE
và FAILED
từ ping và thời gian.
Vòng lặp thứ hai bên trong sẽ ping và kiểm tra bảng arp cứ năm phút một lần để xác định xem điện thoại có ở nhà không. Với ba ping 'FAILED' liên tiếp, điện thoại không ở nhà. Một 'REACHABLE', khi điện thoại không ở nhà, sẽ khiến điện thoại trở về nhà (làm gì đó). Có các kiểm tra để xác thực địa chỉ IP và quay lại vòng lặp bên trong đầu tiên nếu cần chỉnh sửa.
#!/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