Bluetooth Proximity Detection
Since getting my Raspberry Pi 2 back in February, I’ve wanted to build a gadget that could detect when I’m nearby and take some action. This was the underlying idea for my morning greeter project.
TLDR; I used Bluetooth to check if my iPhone/Apple Watch was nearby. Here’s the code.
A quick search on the Internet shows that the usual way of doing something like this with a Raspberry Pi is through a PIR (Passive Infra Red) sensor. There are many tutorials available online, including a cool “Parent Detector” project from the official Raspberry Pi website that is geared towards kids learning to hack with the Pi.
However, there is one major drawback to this approach – the PIR sensor cannot differentiate between different people (or people versus pets for that matter). For my morning greeter, I wanted it to be able to tell if it was me or my wife who had walked downstairs into the kitchen.
Fortunately (Unfortunately?), like many people these days, we have our smartphones with us all the time – especially if we’re getting ready to leave the house. So I figured a good way to detect who was nearby would be to check which phone was nearby.
Just about every smartphone is equipped with WiFi and Bluetooth, each with their own unique addresses. While WiFi is probably the easiest and most reliable way to detect if the device is connected and at home, I couldn’t find an easy way to detect the distance (i.e. proximity) of the WiFi enabled device. So I focused on looking for ways to do this using Bluetooth.
This proved to be more difficult with our iPhones due to the security policies in iOS. The iPhones do not connect to (non-Apple) Bluetooth devices unless the user opens up the Settings app and navigates to the Bluetooth page. This would totally defeat the purpose of the morning greeter, since I may as well just lookup the information on my phone after I’ve pulled it out.
So I needed a way to detect if the phone was nearby without any human interaction with the phone itself. I found bits and pieces of information and code snippets online for doing this. I needed to weave them together and do quite a bit of trial-and-error before getting something that worked.
Initially, I tried using a combination of the rfcomm
and hcitool
shell commands but this was very hacky. The commands would sometimes hang for upwards of 10-15 seconds before returning, and the return values were inconsistent.
Eventually I found some code on Github by Daniel Agar that worked really well. I adapted it into the sample code below.
Sample Code
A bonus for using Bluetooth, it works for both our iPhones and Apple Watches because they each have a unique Bluetooth address. I think this method should work for any smartphone/smartwatch/device equipped with Bluetooth.
You can find the full code on my Github