iBeacon Enabled Beer Fridge
This project began with our team’s vision of a beer fridge that would only unlock for those employees who were up to date on their timesheet. And if we ignore all the people who simply reached down and unplugged the Raspberry PI, or all the times the WIFI adapter stopped responding or how the constant brownouts kept corrupting the server files on the SD card, then this is exactly what we built.
Despite our many struggles, building this fridge was a project our team took on with great enthusiasm as it involved our two great passions – technology and alcohol. I will briefly go over the basic setup, but my intention for this blog post is to focus mainly on the iBeacon integration which, in my opinion, presents the most useful learning that came out of this project.
We tackled the physical elements first and decided an electromagnet was our best option for a lock. With 12 volts applied the magnet would hold firm with over 400lbs of force. An HTTP Node server running on a Raspberry PI was the easy choice to switch the magnet on and off. It had two endpoints to lock or unlock the door. Since the GPIO pins on the PI only output 3 volts, we used a 12 volt relay to control power to the higher voltage magnet. Later on, during testing, we also introduced a speaker to give an audio tone as needed feedback when the lock was released. With all of our components confirmed working we drilled and tapped into the fridge casing to securely mount the magnetic lock and 3D printed a small plastic case to house the electronic components.
The next hurdle was identifying our thirsty user. We recently released a mobile app allowing our 600+ employees to log in and stay updated with company information as well as search users, book conference rooms and perform other administrative tasks. By placing an iBeacon configured Gimbal series 20 beacon on the inside of the front glass, we were able to leverage our app as a means to identify the user and initiate the network connection to unlock the door.
Beacons are great for determining proximity, but since the fridge was in a common location where people tend to congregate, we really wanted to ensure our user’s intention. After working through various approaches, we decided a tap to unlock interaction made the most sense. We wanted our user to be able to just pull out their phone and hold it up to the beacon on the fridge in order to unlock the door. Our original goal of accomplishing this with the device backgrounded using iBeacons (vs NFC chip, to which apple does not currently offer a public API) presented significant challenges which we were never quite able to get working with the reliability we wanted.
A BLE or Bluetooth low energy beacon does nothing more than periodically broadcast a radio frequency with a packet of data. When you hear terms such as iBeacon or Eddystone those actually refer to a protocol for the format of that data. These beacons are only useful because their signals can be detected by devices and identified to determine physical proximity as context for an app.
There are three basic types of beacon proximity events that matter: entering a region, exiting a region, and ranging beacons within a region. Regions, in this case, refer to those areas where the phone is within range of the BLE signals. Depending upon the app lifecycle the responsiveness to each of these events varies. Entering and exiting events occur when an app detects a particular beacon for the first time and when it has stopped detecting a beacon after an undetermined period of time. Exit events are far less responsive than entering events. Most importantly enter and exit events work when the app is either running or not, but when backgrounded the app only has a limited window in which to execute its code.
Ranging events, on the other hand, occur at about a 1-second rate and include signal strength data that can be used to track how the signal is changing. By collecting and averaging the signal data to eliminate intermittent drop out or spikes, it’s possible to finely control the circumstances in which an app responds to beacon events. A great example is to improve the response time of the aforementioned exit events.
In our case detecting something as close as a tap was not easily accomplished without turning down the beacon signals dramatically. At such low power levels, however, those signals were found to be unreliable and erratic. Implementing ranging and checking for the average signal strength to rise above a certain threshold was the only way we were able to get tap interaction to work the way we wanted. But ranging has one significant drawback. It generally only works when the app is active.
There are two workarounds to this issue. One is simply to ask the os to extend background running time. Assuming resources are available this works fine for about 3 mins before the os kills the process. In many situations this would probably work fine, but not in our case where users were likely to be hanging around in close proximity for an extended period of time prior to unlocking the fridge.
The second, less desirable approach involves allowing location updates to occur in the background. Once enabled, this allows ranging within a region to run almost indefinitely. In our tests this worked with some reliability, but on many occasions, especially after long periods of inactivity or upon restarting the device background ranging failed to trigger in a timely enough manner.
After burning through countless hours iterating and testing it became clear that the behavior we were after just wasn’t going to work reliably enough with the app backgrounded. So we instructed our users to launch the app prior to tapping their device in addition to displaying an onscreen button allowing users to unlock the fridge.
Of course, by this point, everyone was pretty fed up with our buggy over-engineered experiment and more often than not the chord was pulled and the fridge was empty. Timesheets be damned.