Hi,
I am really thankful for this thread (surprisingly it seems that there is not much discussion going on in the web at all about this topic) as it seems to be the only way that works in a stable manner.
I chose perl to implement the above concept on a Raspi2. I am sure the script can be improved (I am not exactly a perl expert), but it works fine for me.
Input: IP Address
Output: 1=IP detected, 0=IP not deteced
I use 4 cron scripts in parallel (every 5 minutes) to detect presence of the 4 phones in my household, each cron-script invoking the belowâs perl script and depending on the result triggers an openhab-rest-api to set a switchâŠ
Script to detect iphone âdetect_ip.plâ:
#!/usr/bin/perl -w
#
# script will try to reach ip address 30 times (hping3 not always "wakes up" the iphone)
# wait time between the pings: a random number of 1 - 10 secs (would probably work if you fix the sleep to 10 secs as well)
#
#
# Input-Parameter: Ip-Address
# Output-Parameter: 1 = ip-device deteced, 0 = not detected
#
use strict;
my $ip = $ARGV[0];
if (not defined $ip) { die "no IP address!\n"; }
exit (&checkIPpresence);
sub checkIPpresence {
# first flush arp entry for ip
system "sudo ip neigh flush dev eth0 $ip";
#### hping3 not always wakes up iphone - trying 30 times should be enough to be stable...
my $counter = 30;
while ($counter > 0) {
$counter--;
# hping3 to ip
system "sudo hping3 -2 -c 10 -p 5353 -i u1 $ip -q >/dev/null 2>/dev/null";
# wait 0.5 sec then check if mac address shows up in arp
select(undef, undef, undef, 0.5);
if (&checkARP) {
return 1; # 1 = true, 0 = false;
}
#wait between 1 and 10 secs then arp-check if mac is found
sleep (1 + int rand(10));
}
return 0; # 1 = true, 0 = false;
}
sub checkARP {
my $arp = "sudo arp -an $ip";
open (ARP, "$arp |") or die "cannot run arp '$arp'\n$!\n";
my $i = 0;
if ( defined (my $line = <ARP>) ) {
chomp($line);
close ARP;
if ($line =~ /(.+:.+:.+:.+:.+:.+)/) {
return 1; # 1 = true, 0 = false;
}
}
close ARP;
return 0; # 1 = true, 0 = false;
}
The cron-scripts executed every 5:
#!/usr/bin/perl -w
use strict;
use warnings;
use Data::Dumper;
# define openhab server IP, openhab switch-item name, and ip of iphone to be checked
my $openhabServerIP = "<your openhab server ip address>";
my $openhab_item = "<your openhab switch>";
my $ip = "<ip address of iphone to be tested>";
# define system commands to turn switch on/off and IP of openhab server
my $openhabON = "curl --header \"Content-Type: text/plain\" --request POST --data 'ON' http://$openhabServerIP:8080/rest/items/$openhab_item";
my $openhabOFF = "curl --header \"Content-Type: text/plain\" --request POST --data 'OFF' http://$openhabServerIP:8080/rest/items/$openhab_item";
# run the detection script and pass along the ip address of the phone,
# depending on the return code, set openhab item to on / off
system ("/home/pi/perl.sources/find_iphone/detect_ip.pl $ip");
my $returnCode = $? >> 8;
if ($returnCode) { system ("$openhabON"); }
else { system ("$openhabOFF"); }