I've got a reasonably interesting setup of MisterHouse (a nifty Perl-based home automation program) running on a Linux machine upstairs, that does stuff like turn on lights automatically when it's getting dark or when I enter a room, turn lights off when there hasn't been any activity in a room after a predefined time, and so forth. Maybe I'll post more on that later.
One thing that's missing, though, is a good way for the server to know if I'm home. As I mentioned, there are some lights that come on automatically when it gets dark, but some of that is really kind of a waste of energy if I'm not actually home. (Of course, some lighting would be good so our dogs can get around, but I think they'd be fine with a smidge fewer lumens than we expect.)
One suggestion that I've seen is to install a battery powered motion sensor (like this one somewhere inconspicuous in your car. This broadcasts on the X10 wireless spectrum, and would likely be within range if your car is at home. It broadcasts “motion” and “still” (i.e. “no motion”) signals, as well as “light” and “dark”, so it will send signals even if it doesn't see movement. Then, presumably, you can configure MisterHouse so that, if it notices these wireless signals, it assumes that you are home.
However, this solution has a couple of unpleasant attributes:
- It requires you to stick a motion sensor in your car
- Motion sensors are ugly
- It's not going to transmit continuously enough for your home automation system to know you're “still” there
- There's no way you'd be able to pick up chicks in your ride if they see ugly motion sensors, plus they'd probably think they were cameras and get all creeped out
Another way you could do it (that would be fantastically cool) would be with RFID. If, somehow, you carried an RFID tag around with you most of the time, a long-range RFID reader could tell when you're home and alert MisterHouse appropriately. This would be sweet. One idea (and I don't know if this is my own, or one that I read somewhere) is to put the RFID tag on your keychain, and then embed a reader in a hook where you hang your keys when you come in the door. That would work great, as long as you are diligent about putting your keys there as soon as you walk in the door. Me, that's not how I operate. As soon as I walk in the door, I like to baseball-pitch my keys into a neighboring town and/or state for convenience when I'm about to leave again. Oh, and also, I don't have any RFID stuff yet, so I'd have to buy some and learn it and integrate it. Devil you know and all that.
So, after getting my (awesome) iPhone and pairing it with my wireless network, I realized there was another possibility–if the phone is currently on the network, that's a pretty good indication that I'm home. My phone is always on, and always with me, so it seems there's a fairly low likelihood of false positives and false negatives. My basic plan is to try to ping the phone on some frequent basis, maybe once per minute, and see if it responds. If it does, then tell Misterhouse that I'm home.
One caveat: I use DHCP on my home network, so it's theoretically possible that I could have different IP addresses each time I join the network. Since I hacked my Linksys WRT54G to use DD-WRT, I could configure the router to give my phone a static DHCP assignment. That's too easy, though, so I decided I'd try to learn a bit and ping the phone by its MAC address (which is hardware-specific and never changes) instead of its IP address. Your system maintains a mapping from MAC address to IP address internally. This mapping is done via a protocol called ARP.
First, I looked in my phone settings to determine my MAC address. If you're a lucky iPhone user, too, you can find your MAC address at Settings > General > About > Wi-Fi Address, like so:
From this, I know that my iPhone's MAC address starts with 00:1B:63.
Next, I logged into my Linux machine upstairs (the one running MisterHouse) and sent a “ping” to the network broadcast address, which tells all hosts to respond:
[jason@assmonkey ~]$ ping -b 192.168.1.255 WARNING: pinging broadcast address PING 192.168.1.255 (192.168.1.255) 56(84) bytes of data. 64 bytes from 192.168.1.101: icmp_seq=1 ttl=64 time=53.5 ms 64 bytes from 192.168.1.158: icmp_seq=1 ttl=64 time=56.9 ms (DUP!) 64 bytes from 192.168.1.101: icmp_seq=2 ttl=64 time=77.4 ms 64 bytes from 192.168.1.158: icmp_seq=2 ttl=64 time=178 ms (DUP!) 64 bytes from 192.168.1.101: icmp_seq=3 ttl=64 time=101 ms 64 bytes from 192.168.1.158: icmp_seq=3 ttl=64 time=201 ms (DUP!) --- 192.168.1.255 ping statistics --- 3 packets transmitted, 3 received, +3 duplicates, 0% packet loss, time 2000ms rtt min/avg/max/mdev = 53.509/111.650/201.997/58.103 ms [jason@assmonkey ~]$
This has the effect of filling in the ARP cache on your system with the MAC addresses of all machines that responded to the ping. Now, I can look in the cache with the following command:
[jason@assmonkey ~]$ /sbin/arp -a ? (192.168.1.158) at 00:1B:63:XX:XX:XX [ether] on eth0 Crap (192.168.1.1) at 00:18:39:XX:XX:XX [ether] on eth0 macbook (192.168.1.101) at 00:17:F2:XX:XX:XX [ether] on eth0 ? (192.168.1.131) at 00:0F:1F:XX:XX:XX [ether] on eth0 [jason@assmonkey ~]$
Bingo! Since we know that the MAC address started with 00:1B:63, we can tell that its IP address is 192.168.1.158. Now, a good old-fashioned ping confirms that the phone is on the network:
[jason@assmonkey ~]$ ping 192.168.1.158 PING 192.168.1.158 (192.168.1.158) 56(84) bytes of data. 64 bytes from 192.168.1.158: icmp_seq=1 ttl=64 time=51.3 ms 64 bytes from 192.168.1.158: icmp_seq=2 ttl=64 time=2.61 ms --- 192.168.1.158 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 2.619/26.964/51.310/24.346 ms [jason@assmonkey ~]$
But, oh noes! A few minutes later, I retried the ping, and found this:
[jason@assmonkey ~]$ ping 192.168.1.158 PING 192.168.1.158 (192.168.1.158) 56(84) bytes of data. --- 192.168.1.158 ping statistics --- 10 packets transmitted, 0 received, 100% packet loss, time 8999ms [jason@assmonkey ~]$
The phone wasn't pingable anymore! I did some digging around, and came to the conclusion that the iPhone disconnects from the wireless network when you're not actively using it. This is probably done to conserve power. Unfortunately, though, this kind of defeats the point of the entire attempt, as I need the phone to be pingable on a continuous basis in order for my presence detection scheme to work.
So, that's why I put “almost” in the title. Anyone know a more clever way to do this?