2

I'm trying some home automation. My goal is to send an HTTP request when my Android phone leaves my home's Wifi, and send a different HTTP request when it rejoins. The goal is when I leave home - more specifically, when my phone leaves home - my IP camera's motion detection is armed. Then, when I return home, it's disarmed. The IP camera has an HTTP interface where the arming and disarming can be done programmatically.

This means that when I'm away from home, the webcam emails me when it detects motion at the front door. Because my phone rejoins Wifi about a minute before I actually enter my home, the motion detection is disarmed just before I walk in the door and therefore I don't get an alarm of myself coming in. It also means because my phone is on Wifi as I walk out the door, I don't get an alarm of myself walking out, either.

My current approach involves a cron job running every minute on my Linux server running 24/7 on my LAN. It consists of two Bash scripts. One detects the presence of my phone (returns 1 if the phone is present, 0 if not):

cat /usr/local/bin/detect-phone.sh
#!/bin/bash
arping -D -c 10 -I eth0 nexus4

...and the other users that script to do some automation. It uses arping to detect the device on the network along with the existence of a 0-byte file at /tmp/phone-presence. If one says the phone is present but the other doesn't, then it sends the necessary HTTP request to arm or disarm the motion detection on the webcam.

cat /usr/local/bin/toggle-webcam-alarm.sh
#!/bin/bash
/usr/local/bin/detect-phone.sh &> /dev/null
IS_HOME_NOW=$?
WAS_ALREADY_HOME=0

if [[ -f '/tmp/phone-presence' ]]; then
   WAS_ALREADY_HOME=1
fi

ENABLE_WEBCAM=''

if [[ "$WAS_ALREADY_HOME" -eq 0 && "$IS_HOME_NOW" -eq 1 ]]; then
    /usr/bin/logger "Phone just joined network, disarming webcam alarm"
    ENABLE_WEBCAM=0
    > /tmp/phone-presence
elif [[ "$WAS_ALREADY_HOME" -eq 1 && "$IS_HOME_NOW" -eq 0 ]]; then
    /usr/bin/logger "Phone just left network, arming webcam alarm"
    ENABLE_WEBCAM=1
    rm /tmp/phone-presence
fi

if [[ ! -z "$ENABLE_WEBCAM" ]]; then
    /usr/bin/curl "...some URL that accepts $ENABLE_WEBCAM..." &> /dev/null
fi

This does work, but the presence detection is unreliable. My log is filled with entries like:

tail /var/log/messages
...
Sep  6 10:37:11 logger: Phone just left network, arming webcam alarm
Sep  6 10:38:01 logger: Phone just joined network, disarming webcam alarm
Sep  6 10:47:11 logger: Phone just left network, arming webcam alarm
Sep  6 10:48:02 logger: Phone just joined network, disarming webcam alarm

And those entries aren't because I left home or because I touched my phone at all. My phone should have been on the Wifi network the entire time (well, I didn't tell it to disconnect at least and it had a strong signal).

So, my current solution isn't reliable. I occasionally get emailed a picture of myself as I walk in or out. Increasing the count specified with -c for arping doesn't usually have an effect on improving reliability of the detection of my phone, and besides, if I set it absurdly high, it will start causing problems as the cron job runs every minute.

I don't really mind if it takes a few extra minutes to observe the phone leaving home, but it needs to take a minute or less between when my phone actually rejoins Wifi to when my webcam motion detection is disarmed so I don't get alarms of myself. The webcam must not be erroneously armed when I'm home, nor must it be erroneously disarmed when I'm away from home.

Some other approaches I've considered but don't know how to implement:

  • Query my router (running Tomato) via SNMP every minute to see if the device is still on the network instead of using arping.
  • Configure dnsmasq on the router to run a script when it issues a DHCP lease to the phone as a result of the phone connecting to Wifi. But, I don't know how that would work for the opposite scenario where the phone drops off the network. The phone has a static DHCP address, so while the IP assigned to the phone never changes, it still requests one via DHCP.
  • Use Llama to handle the presence detection. I'm already using Llama to automate some things on my phone successfully based on my location. That's fine for sending the request when the phone joins Wifi, but not when it leaves Wifi, because both HTTP requests must be sent on the LAN: they contain sensitive data. Now, I do have the option of using Apache as a proxy. I have a Linux server running a public-facing SSL-protected Apache instance, and if need be, I could (well, with help) configure it to allow the request to be made over SSL on the Internet and then forwarded to the webcam on the LAN. That way, the HTTP requests could be sent over the Internet, but short of guessing the URLs, nobody would be able to access them as the requests would be encrypted.

So, what approach would you recommend I take to reliably handle this scenario? Again, the high level goal: send one HTTP request when my phone leaves home, and send a different one when it arrives back home.


Thanks for the suggestions so far. Here are some updates:

  • My phone doesn't respond to a normal ICMP ping reliably. Sometimes it replies immediately and sometimes it times out.
  • Tomato does indeed have wl but it seems to be very inaccurate. In particular, it thinks a device that hasn't been on my LAN in months is still present and has a good signal strength. That seems unlikely as it's sitting on a shelf with the battery removed.
  • I have no issues with using IFTTT (although I would initially prefer something entirely local). However, while it could easily handle the geofencing aspect, I don't see how it could actually perform the necessary triggers to arm and disarm the webcam alarm which requires sending those two HTTP requests.
  • Thanks for the Java class suggestion, but unless things get really desperate, I'd rather not have to write an entire Android application to handle this scenario. Plus, with Llama and IFTTT, there are already several options to handle the geofencing issue. Llama can also perform various actions when Wifi is connected or disconnected.

I think I did find a way of significantly improving the reliability of the current arping approach. I turned off "Wi-Fi Optimization" in Android's settings. Since then, I only had one false positive drop appear in my log in the past 8 hours whereas normally it would be about one per hour. I'll keep this setting disabled for a while longer to see if it really helps. My theory is it keeps the Wifi connection alive more reliably and thus the phone is more likely to respond to any Wifi traffic.

I was also able to set up the Apache SSL proxy for the two requests (one to arm the webcam alarm and another to disarm it) so, if need be, I can send those requests over the Internet now securely.


After a few days of watching logs, it looks like this is now completely reliable after turning off "Wifi Optimization" on my phone. I'm guessing the Wifi connection slept on occasion and dropped off the network if no program or service on the phone used it after some time.

user3466413
  • 805
  • 1
  • 7
  • 16
  • 1
    Did you look into using the ConnectivityManager class. This way, the App in your phone can detect if it changes from WI-FI to mobile vice versa. http://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html – alpinescrambler Sep 07 '14 at 02:06
  • I haven't used tomato in years, but does your router have the `wl` command? If so, you could telnet into the router, and `wl rssi ` to monitor the phone's signal strength (or whether it's even there). – 323go Sep 07 '14 at 03:30
  • Not sure how you feel about using another service, but IFTTT.com has triggers for Android - you could trigger either off of your phone joining a wifi network or off crossing a geofence set appropriately far out from your home. I'm not sure which activation channel would work best for you, but there's a lot available, which might let you easily get the notification - https://ifttt.com/channels – Andy Tinkham Sep 07 '14 at 17:37
  • By the way, for those of you thinking of more home automation ideas based on your own presence: I can turn on my desktop using WOL when I get home, and although I can't think of what to do with them yet, I also have Belkin WeMo switches which are Wifi-controllable power outlets. Most of this could even run directly on my router; you just need a 24/7 Linux system! – user3466413 Sep 09 '14 at 00:21

2 Answers2

0

Just did a quick test, and my android phone responds to ordinary pings.

You could execute a cron job that does something like this:

$ ping -c 5 192.168.1.131
PING 192.168.1.131 (192.168.1.131) 56(84) bytes of data.
64 bytes from 192.168.1.131: icmp_seq=1 ttl=64 time=28.6 ms
64 bytes from 192.168.1.131: icmp_seq=2 ttl=64 time=51.4 ms
64 bytes from 192.168.1.131: icmp_seq=3 ttl=64 time=73.9 ms
64 bytes from 192.168.1.131: icmp_seq=4 ttl=64 time=97.4 ms
64 bytes from 192.168.1.131: icmp_seq=5 ttl=64 time=16.0 ms

--- 192.168.1.131 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
rtt min/avg/max/mdev = 16.067/53.491/97.404/29.558 ms

Parse the output, and if you get at least three pings back, your phone's here (although I'd expect all five pings to come back without any issues). Not sure why ARP pings are unreliable.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
0

Just my two cents but you can use nmap to query your router and check the devices you are interested in (by MAC or IP) and send queries at regular intervals to see if they are still alive.

You should give an IP range to the nmap tool to scan your network (something like 192.168.1/255) and get a file of the results, then just parse it out.

With this approach you can have "presence" detection according the existence of a user on your wireless network. Be careful with iOS as those devices are connected on and off even if they haven't moved an inch.

Hope this helps.

ProgrammerV5
  • 1,915
  • 2
  • 12
  • 22