iBeacons and Hue Lights Tutorial Part 1: Introducing The Beacon Solution
This is post 1 of 4 in the series “iBeacons and Hue Lights Tutorial Series”
- iBeacons and Hue Lights Tutorial Part 1: Introducing The Beacon Solution
- iBeacons and Hue Lights Tutorial Part 2: Implementing a Node.JS Server
- iBeacons And Hue Lights Tutorial Part 3: Integrating Node.JS with iOS
- iBeacons And Hue Lights Tutorial Part 4: Typhoon Dependency Injection Framework
A small band of Gorillas created a three-week iBeacons and Hue Lights project using different technologies. In this four-part series we will elaborate on the three main goals of this project and provide a tutorial along the way:
1. Implement Beacon SDK to connect the iPhone to beacon devices through Bluetooth.
2. Implement a Node.JS Server to manage and handle a Philips Hue Bridge with Hue Lights.
3. Implement Typhoon Injection Framework in the iOS App.
In Part 1 of this series, we introduce the project and beacon solution. You will get a sneak peek of how to implement beacons and integrate them with other technologies. See Part 2 and learn how to implement a Node.JS Server.
So let’s get into it!
Why iBeacons?
Is there a way to know when a client reaches your store? What if you could measure how many customers stand in front of a product or piece of clothing? What if you could bring featured product information to a user if he or she gets near to or lifts a product? Well, you can use Beacons to make this happen!
iBeacons, generally called beacons, are proximity devices. They let you know when someone enters an area.
Beacons bring a lot of advantages for commercial use, personal use, and increased productivity. You can brainstorm with your friends or colleagues about how you can use a sensor proximity device that tells you if you enter or exit an area. There are so many of uses and scenarios that you can bring to the table.
For example: Think about a construction zone where you want to keep trucks with flammable material out of a dangerous area. You can set up beacons in the danger area and connect them with smartphones of the truck operators. Whenever a truck operator is close to a dangerous area, they will receive a warning to avoid the zone!
Now you have an idea of how you can use beacons in the real world and why these small devices are so great.
The Mobile Project
The goal of this project is to help a user find a location through a beacon and the Philips Hue light bulb. When the user opens the app a list of available locations (beacons) would be displayed. The user would choose one of these locations and begin tracking how close he or she is to it.
As the user gets closer to the location, the Philips Hue light bulb would change its light intensity from dim to brighter. Likewise, the distance between the user and the location should be shown on the application.
After the user reaches the location, the light would “breathe” and show the user that he or she has reached the destination. Then, the user would be granted access to a menu in the app to change the light’s color. Afterward, the user can exit the location and return to the list. This action will turn off the light and restart the experience.
Project Architecture
UI Design
Our UI Design was simple to present the technology, we got help from one of our UI/UX Practice Leads, Paula Chavarria. She created the mockups and final design. We also implemented some radar animations that emulate the User approaching the beacons’ location. For the radar, we used a third-party pulsator and added custom code for light bulbs moving when receiving data from the beacons.
Estimote Beacon SDK
Should I use Estimote Beacon SDK or CoreLocation iOS Framework?
Estimote Beacon SDK Pros
- Estimote brings all the necessities to work with Beacons (development devices, SDK, iCloud, Customer Support, and more).
- Estimote has different base projects that you can download that can facilitate your work.
- Sample Application will give you some ideas of how to use and interact with beacons.
CoreLocation
iBeacons is a protocol developed by Apple and the CoreLocation framework has full support to work with any beacon device. We decided to use CoreLocation in order to learn the basics and create a base-manager that works with any beacon manufacturer.
Beacon Solution
You can use Estimote SDK or CoreLocation to manage your connection to beacons.
The functionality that you have to implement is similar in both. You can have sample code for Estimote or CoreLocation in a quick search. The following solution is what we implemented and the steps that we think you will need to implement in order to have your project working.
- Add Location key “Privacy – Location Always Usage Description” into your Info.plist.
- Add Estimote Beacons SDK or CoreLocation Framework to your project( note: Estimote will need an Objective-C Bridge if you are on Swift).
- Start/Stop Beacon Monitoring.
- Start/Stop Beacon Ranging.
- Work with Beacons Delegates( LocationManagerDelegate ) to handle the information received.
Step 1: Add Location Key “Privacy – Location Always Usage Description”
If you want to receive beacon signal even when the app is not running:
Add the new key into your Info.plist “Privacy – Location Always Usage Description” and the string will be a popup message that prompts permissions when the user runs the application for the first time.
Step 2: Add Estimote Beacons SDK or CoreLocation Framework
If you want to work with Estimote, you can download the Estimote SDK or add it to your project using CocoaPods ( Podfile ).
# Pods for Estimote Beacon SDK
pod 'EstimoteSDK' , '4.14.1'
To use the CoreLocation, just import the framework:
import CoreLocation
Remember to instantiate the location manager:
// Add a property to hold the corelocation manager and instantiate it
let locationManager = CLLocationManager()
Step 3: Start/Stop Beacon Monitoring
Think of Beacon Monitoring as a geofence – a virtual barrier often defined by a set of geographical coordinates.
When Monitoring you get ‘enter’ and ‘exit’ Events. Monitoring works even if the app is not running.
Here is a sample code to start monitoring:
func startMonitoring(uuid: String, major: CLBeaconMajorValue, minor: CLBeaconMinorValue, identifier: String ) {
self.locationManager.startMonitoring(for: CLBeaconRegion(
proximityUUID: UUID(uuidString: uuid)!,
major: major, minor: minor, identifier: identifier))
}
There are three values in Beacons that are used to differentiate beacons:
- UUID: Main Identifier for a beacon or a group of beacons.
- Major: Most commonly used to differentiate beacons.
- Minor: Most commonly used to differentiate beacons.
A CLBeaconRegion is used to receive the beacons broadcast. You can monitor up to 20 regions.
Step 4: Start/Stop Beacon Ranging
Beacon Ranging actively scans for any nearby beacons and delivers results every second.
Beacon Ranging gets beacon signal strength “which diminishes as the signal travels through the air.” This enables the receiver device to make a rough estimation of how far away the beacons are.
Here is a sample code to start/stop ranging:
func startRangingWithLocationManager(in beaconRegion: CLBeaconRegion) {
self.locationManager.startRangingBeacons(in: beaconRegion)
}
func stopRangingWithLocationManager(in beaconRegion: CLBeaconRegion) {
self.locationManager.stopRangingBeacons(in: beaconRegion)
}
Beacons can be grouped by UUID, this way you can start Ranging beacons in the same Region.
For this project; we implement Ranging because we need the proximity and accuracy to know the distance from the beacon and the chances when we walk close or far of the beacon area.
Accuracy gave us the distance value that we can check and decide if the User is close enough to the beacon to handle the lights!
Note: you can get the proximity and accuracy value from beacons when you start ranging.
Step 5: Beacons Delegates (LocationManagerDelegate)
We worked with Beacons Delegates (LocationManager Delegate) to handle the information received.
Here is a sample code to handle the data received when ranging:
func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
if beaconViewDelegate != nil {
beaconViewDelegate!.beaconsInRange(beaconList: beacons)
}
else {
print("ViewDelegate not set, this is required to update your ViewController when using APIHelper as Delegate.")
}
}
The CLBeaconRegion is used as a filter to get the list of beacons required.
CLLocationManagerDelegate sends the beacon’s list to the function and then we can do our code or pass it to a different controller to work. In our case, we created a beaconViewDelegate that sent the data to the viewController that needed to be Updated.
// Delegate to send updates to the main View that is using Beacons.
protocol BeaconManagerDelegate {
func beaconsInRange(beaconList: [CLBeacon]);
}
Here is a sample code of how to use the Delegate:
Set the delegate on your controller:
// Set Radar View Controller as ViewDelegate to update the screen.
BeaconManager.sharedInstance.beaconViewDelegate = self
Use Extension to handle the delegate function:
// MARK: - BeaconAPIHelperDelegate
extension RadarListViewController: BeaconManagerDelegate {
func beaconsInRange(beaconList: [CLBeacon]) {
for beacon in beaconList {
let distance = BeaconManager.sharedInstance.locationInMeters(beacon: beacon)
if distance != "" {
if beacon.major == 55002 {
self.beacon1.beaconDistance = distance
}
else if beacon.major == 55417 {
self.beacon2.beaconDistance = distance
}
else if beacon.major == 23974 {
self.beacon3.beaconDistance = distance
}
DispatchQueue.main.async {
self.tableView.reloadData()
self.lightBulbA.reloadData()
self.lightBulbB.reloadData()
self.lightBulbC.reloadData()
}
}
}
}
}
The BeaconsInRange delegate function is used to update the UI. Remember to use the main thread for this.
If you want to use Monitoring, just include didEnterRegion and didExitRegion functions into your CLLocationManager.
That’s all you need to implement and work with beacons and get the delegate data using CoreLocation!
In the next part of this series, we will introduce the Phillips Hue Lights and how to integrate this with beacons.
*Note: This post was written by Brian Rojas and Jorge Mendoza. We would like to thank Andres Sirera for being the Project Manager and Paula Chavarria for being our Tech Lead and UI/UX expert.