How to set up your project to work with iBeacons
How to turn an iPhone into an iBeacon
Want to experiment with iBeacons but can’t afford the technology? Perhaps an iPhone is the answer…
What are iBeacons?
iBeacons are simple devices that your iOS device can detect within a short range. The iBeacon allows the user to start interacting with it when in its proximity.
In this tutorial, we’ll help you set up your project to work with iBeacons.
You might not want to invest in an iBeacon straight away. Particularly if you’re only in the development stages of a project, or if you’re just doing some research and development.
An easy solution is to turn your iPhone into an iBeacon, and it’s easier than you think.
The first step to set up your project to work with iBeacons is to make sure you have Bluetooth enabled on your device.
Setting up the emitter
// Needed module for iBeacons @import CoreLocation; @import CoreBluetooth;
The above module is necessary in order to get all the BLE magic working. Here are the properties you will need to get the phone transmitting like an iBeacon:
@interface EmitterViewController () // The region defined by our beacon, with all the information representing it @property (strong, nonatomic) CLBeaconRegion *beaconRegion; // The option we will use to set up the phone as a peripheral @property (strong, nonatomic) NSDictionary *peripheralData; // Object responsible of transforming your phone into a transmitter, with all the method that goes with it @property (strong, nonatomic) CBPeripheralManager *peripheralManager; @end
Those properties can either be in your .m or .h file (it has no importance for this tutorial).
What are the properties of iBeacons?
An iBeacon is defined by three distinct properties :
A UUID
A ‘major’ value
A ‘minor’ value
The UUID is there to make sure your beacons are linked to your application. This also ensures other beacons won’t interfere with the experience you put in place for the user.
To create a UUID simply:
Open terminal
Type uuidgen
Copy the result
The major and minor values differentiate the beacons within your app. Usually, the major will be used to represent a room and the minor will be a beacon within that room.
Ready to broadcast with your iBeacon
It's time to set up the beacon and start broadcasting:
- (void)prepareBeacon { NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"8532DD11-5F36-4120-ADF2-C32A14145D06"]; self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:1 minor:1 identifier:@"com.Brightec.iBeacon"]; } - (void)startBeacon { self.peripheralData = [self.beaconRegion peripheralDataWithMeasuredPower:nil]; self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil]; }
In startBeacon, you’ll keep a strong copy of the peripheralData and peripheralManager to ensure they won’t be cleaned in the memory by accident.
The delegate method
Calling the startBeacon
method doesn’t necessarily tell you if the device successfully started broadcasting as a beacon or not. This is why we set our class as a cbperipheralmanagerdelegate
in the interface. This way we have the following delegate method:
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral { if (peripheral.state == CBPeripheralManagerStatePoweredOn) { // Update your UI to indicate the beacon is now on [self.labelStatus setText:@"Beacon currently broadcasting"]; [self.peripheralManager startAdvertising:self.peripheralData]; } else if (peripheral.state == CBPeripheralManagerStatePoweredOff) { // Update your UI to indicate the beacon is now off [self.labelStatus setText:@"Beacon currently not broadcasting"]; [self.peripheralManager stopAdvertising]; } else { // Update your UI to indicate there was something wrong NSLog(@"Something went wrong, current status : %ld", (long)peripheral.state); [self.peripheralManager stopAdvertising]; } }
In the delegate method, you can update your UI to communicate to the user the current status of the beacon.
Setting up the receiver
// Needed module to listen for iBeacons @import CoreLocation;
Unlike before, you just need CoreLocation
to listen and discover iBeacons :
@interface ReceiverViewController () // The kind of region we will be listening for @property (strong, nonatomic) CLBeaconRegion *beaconRegion; // Use location services to find beacons @property (strong, nonatomic) CLLocationManager *beaconLocaliser; @end
The class is a CLLocationManagerDelegate
because we will want to use the class delegate for each occurrence of entry into the influence zone of an iBeacon.
Setting up the iBeacon
First in your viewDidLoad
you want to set up the location manager and prepare it to listen for the iBeacons, the code here is very similar as if you were doing geo-fencing.
- (void)viewDidLoad { self.beaconLocaliser = [[CLLocationManager alloc] init]; [self.beaconLocaliser setDelegate:self]; }
In order to prepare your beacon to listen, you will have to listen to the UUID of your beacons (as we created it earlier). If we were using actual iBeacon devices, you would have to set them up properly beforehand.
- (void)initBeaconLocaliser { NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"8532DD11-5F36-4120-ADF2-C32A14145D06"]; self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.Brightec.iBeacon"]; [self.beaconLocaliser startMonitoringForRegion:self.beaconRegion]; }
So we are re-using the same UUID and bundle identifier as before ensuring our phone will be picked up by our beacon listener. Once again we keep a strong reference in the code to make sure nothing will be accidentally cleaned by ARC.
The delegates
The delegates here will fire when entering and leaving the zone of influence of an iBeacon. When detecting the signal of a beacon you will want to start ranging the beacon in order to get more information.
// when picking up the signal of an iBeacon - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { [self.beaconLocaliser startRangingBeaconsInRegion:self.beaconRegion]; } // When leaving the signal of an iBeacon - (void)locationManager:(CLLocationManager *)manager didExitRegion:(nonnull CLRegion *)region { [self.beaconLocaliser stopMonitoringForRegion:self.beaconRegion]; }
When you start monitoring the beacons in range, the following delegate method will be called. This will take place every time a piece of information changes (regarding at least one of the beacons in range).
// More information for the beacons in Range - (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region { CLBeacon *beacon = [[CLBeacon alloc] init]; beacon = [beacons lastObject]; NSLog(@"Beacon Major : %@", beacon.major.description); NSLog(@"Beacon Minor : %@", beacon.minor.description); NSLog(@"Beacon Accuracy : %f", beacon.accuracy); if (beacon.proximity == CLProximityUnknown) { NSLog(@"Proximity : Unknown Proximity"); } else if (beacon.proximity == CLProximityImmediate) { NSLog(@"Proximity : Immediate"); } else if (beacon.proximity == CLProximityNear) { NSLog(@"Proximity : Near"); } else if (beacon.proximity == CLProximityFar) { NSLog(@"Proximity : Far"); } }
A quick note regarding the beacon.proximity
, it greatly varies depending on the signal you are receiving. It can be affected by more parameters than just distance (for example a wall, a crowd standing around, etc). You'll have to take that into account. In order to do so you can look at the beacon.rssi
that will give you the beacon signal strength in decibels. Now you are ready to detect your own beacon and create your own experience for your users.
What could you use iBeacons for?
Playing around with iBeacons is a lot of fun; we've even managed to make one out of a raspberry pie (don't ask).
One great idea we had was to install them in museums. Imagine having an iBeacon under every piece of art. They could be used to enhance the experience of visually impaired people or to describe the history surrounding the exhibit. Even to add some gamification for children.
iBeacons have a lot of potential and we really hope you enjoy experimenting with them!
This article was originally written for Brightec by Lionel Mille
Looking for something else?
Search over 400 blog posts from our team
Want to hear more?
Subscribe to our monthly digest of blogs to stay in the loop and come with us on our journey to make things better!