Tutorial: Making a Smarter iBeacon Emitter on iOS with Swift with PubNub | Guest Post

Apple has been using BLE on its devices since the iPhone 4S. Because of that great head start, the iPhone is easier to turn into a beacon than any other platform. In fact, Apple’s iBeacon protocol was the first to take advantage of the great qualities of BLE communication.

In our other tutorials, we walked through an overview of beacon technology and how to build an iBeacon listener (detector).

In this tutorial, we will make a smarter iBeacon emitter! Using PubNub and iBeacon, we can create two-way communication while still keeping the low energy asset of beacons! You’ll want to read a little bit on how we plan on doing this, this article will give you a high-level explanation on how our app is supposed to function. This weird, but simple setup increases the capabilities of iBeacons greatly!

We will first look into how to turn your iPhone into an iBeacon in Swift, and we will build the PubNub structure over it!

What are we waiting for? Let’s build amazing apps! This article is inspired by this example app so feel free to use some of its available source code.

Using your iPhone as an iBeacon

image02

We won’t get into doing the user interface here, we really just want to focus using the iBeacon capabilities of your phone.

Setting up your View Controller

First things first, let’s import our libraries.

import UIKit
import CoreLocation
import CoreBluetooth

That’s all we’ll need for this.

Inside our view controller class, we’ll have variables representing the UUID, the major and the minor of our advertised signal.

let major = 9
let minor = 6
let uuid = NSUUID(UUIDString: "0CF052C2-97CA-407C-84F8-B62AAC4E9020")
var peripheralManager = CBPeripheralManager()
var advertisedData = NSDictionnary()

You can chose any uuid or major and minor as long as the uuid is the same as the one you inserted in the app detecting your iBeacon signal.

Start advertising the iBeacon in a region

You need to create a CoreBluetooth peripheral manager which will control the advertising of your data. Don’t forget to set your View controller as a CBPeripheralManagerDelegate.

To simplify our app, we will start our peripheral manager when the view loads.

The first thing we want to do is build a beacon region. This will create an object defining the data you want to advertise: uuid, major, minor.

The next step is to create a peripheral manager instance. The peripheral manager is the element that will allow us to use the iPhone’s hardware to start acting as a beacon. We will need to set a delegate which will call the peripheral manager’s methods when certain events will be triggered. We set our view controller as the delegate. Don’t forget:

class YourViewController: UIViewController, CBPeripheralManagerDelegate {

For iOS 8 or more, it is necessary for the app to request the user’s authorization to use location tools. This line usually will not suffice. You have to manually add a couple lines in the info.plist file which is located in the “Supporting Files” directory. If you right click on it and open it as “Source Code”, you want to make sure you add these lines inside the “<dict>” markup.

<key>NSLocationAlwaysUsageDescription</key>
<string>Location services required for iBeacon</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location services required for iBeacon</string>

When the user first starts the app, a pop up dialog box will ask the user to authorize location services along with the string we just defined.

image00

class YourViewController: UIViewController, CBPeripheralManagerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
region = CLBeaconRegion(proximityUUID: self.uuid, major: self.major, minor: self.minor, identifier: "com.yourCompanyName.example")
self.advertisedData = region.peripheralDataWithMeasuredPower(nil)
self.peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil)
}
}

Alright, so we generated a dictionary containing the data we want to advertise in the proper format. The region object holds the important data. The measured power argument represents the RSSI power of our emitting device from a meter away. Remember, inside the advertised data, one byte represents this value which is used by the receiver to estimate how far the beacon is. By entering nil, this will return the default RSSI value of your device. That’s probably what you’ll want to do 99% of the time.

Finally we start our CBPeripheralManager. Since we set our View Controller as the delegate, as soon as the manager starts, the peripheralManagerDidUpdateState:peripheral: method of the delegate object (i.e. our view controller) will be called.

func peripheralManagerDidUpdateState(peripheral: CBPeripheralManager!) {
switch peripheral.state {
case CBPeripheralManagerState.PoweredOn:
self.peripheralManager.startAdvertising(self.data)
[...]
}
}

When the method is called with a powered on state, we can start advertising our data. Its up to you to decide how your app will behave for other states.

And that’s all it takes. Easy, right? Just a couple lines and we can start advertising our data! Beautiful.

The next thing we want to do is make our app magical. That’s where PubNub comes it.

Making your iBeacon smarter with PubNub

Getting Started

The first thing you will need is the pubnub library for iOS.

We are going to use cocoa pods. If you don’t use it yet, you’re missing out. Easy installation and starter’s guide here

In your project’s root directory:

$ pod init
$ {your favorite editor} Podfile

Your podfile should look like:

platform :ios, “8.0”
target “YourProject” do
pod ‘PubNub’, ‘3.7.2’
end
target “YourProjectTests” do
end

You can make sure you are using the latest version of pubnub here.

Now you just need to type

$ pod install

Close Xcode, and open the YourProject.xcworkspace .

That wasn’t too hard right? It’s not quite over though.

Use Objective-C libraries in Swift

The pubnub library is written in Objective-C, but we are coding in swift. All you need to do now is to build a bridging header. Create a new Objective-C header in your project called YourProject-Bridging-Header.h for good practice, and type:

#ifdef __OBJC__
#import &lt;UIKit/UIKit.h&gt;
#import &lt;Foundation/Foundation.h&gt;
#import "PNImports.h"
#endif

Now in your project’s configuration panel, go to build settings and scroll down to the “Swift Compiler – Code Generation” section. Set the “install Objective-C Bridging Header” to Yes and in “Objective-C Bridging Header” type the path from your project’s root directory to your bridging header. It’ll be something like “YourProject/YourProject-Bridging-Header.h”

image01

All set? Let’s roll.

Initializing PubNub

For the sake of simplicity, we will code our PubNub behaviour on the same view controller.

We will need to add 2 variables to our class:

let config = PNConfiguration(forOrigin:"your.company.com", publishKey: "demo", subscribeKey: "demo", secretKey:nil)
var channel = PNChannel()

When a user connects to PubNub, he is identified with the content of this PNConfig object. For the scope of this tutorial, we will use demo keys. Get yours here!

In the viewDidLoad method, we will also start PubNub. Add these lines and don’t forget to set your class as a PNDelegate:

PubNub.setDelegate(self)
PubNub.setConfiguration(self.config)
PubNub.connect()
channel = PNChannel.channelWithName("YourCompany_\(minor)_\(major)", shouldObservePresence: true) as PNChannel
PubNub.subscribeOnChannel(self.channel)

We are all set. All we need to do is to define the methods that will be called when events occur on the channel.

There is a long list of methods being triggered for various events, you’ll find it here. We’ll only implement one for our app.

func pubnubClient(client: PubNub!, didReceivePresenceEvent event: PNPresenceEvent!) {
switch event.type.rawValue {
case PNPresenceEventType.Join.rawValue:
PubNub.sendMessage("Come to get your free drink!", toChannel: event.channel)
[...]
}
}

When someone joins the channel, the method is triggered and we send a message to the channel that the end user will receive! The message can be any object in the form of a JSON. Here we just send a string, but you could configure the message to have a receiver variable so that only the user who just subscribed receives it.

That’s it! Our iPhone acts like a beacon that emits information to join the PubNub channel. When the customer is close enough to the iBeacon, his phone will subscribe to the advertised PubNub channel. Our beacon is listening for presence events to the channel and immediately sends a message on the channel for the user to see!

Beautiful. Hope you like it. There is so much more you can do with so little code.

Resources

Guest Authors 

Norvan Sahiner and Sunny Gleason wrote this tutorial series on behalf of PubNub, a platform that allows you to build and scale realtime apps for connected devices.

2 Responses to “Tutorial: Making a Smarter iBeacon Emitter on iOS with Swift with PubNub | Guest Post”

  1. PubNub.subscribeOnChannel(self.channel) gives me an error in swift but if you change it to:
    PubNub.subscribeOn([self.channel]) that seems to build successfully

    Reply
  2. I followed the guide but when I added PubNub via cocoapods and tried to build, I get 6 errors. 1 of which points to the PNPrivateMacro.h file at line 10 saying that “#include — Include of non-modular header inside framework module ‘PubNub.PNPrivateMacro'”

    any clues?

    thanks!

    Reply

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>