Tags

In a previous post, I built the first sling sub-experience prototype – local alerts.  This post continues where the last post left off, adding location information to the sling iOS app. To add to my excitement, I wrote the app in Swift – Apple’s new programming language.  So far I am a big fan of Swift.  I found it easy to get started and harder to master (this is a good thing!).  Less time is taken up dealing with the nuances of a verbose language (like Objective – C, but true of many others) since Swift makes a lot of concepts intuitive and infers my intention. My current plan is to switch my iOS programming to Swift.

The Goal

The goals of this post is to:

  • document the second part of the sling sub-experience – adding location information.
  • document and Swift/iOS programming tips/techniques/constraints I pick up along the way.
  • understand how to go from sling background alerts prototyped in this post to foreground location information.
  • explore the Swift programming language.

Open Source

The prototype iOS app is available at this GitHub location.

Thanks to Those That Went Before

Thank you to Punch Through Design for the Bean BLE peripheral.  It is a great way to prototype Arduino/iOS/Mac apps that use BLE and/or iBeacon.

Thank you to Apple for the Swift language.  While new to Swift, I believe it is a brilliant leap to more of a design driven programming environment.  I was amazed to not be boggled down in layers of methods/functions…stuff worked more like I thought it would.  

Thank you to Ray Wenderlich and the tutorial team.  I believe it was Owen Brown’s post where I found the code for their version of BTDiscovery – a Swift class for discovering BLE advertisement packets.  This work made it easy for me to evolve the code for my needs.  In the process, I learned more about Swift.  The site is an excellent resource for learning iOS programming.

Throughout this post I have linked to many great articles on BLE and iBeacon.  I lean a tremendous amount from the brilliant folks who wrote these posts.  Thank you!

The Prototype

I left the last prototype showing a notification alert to the Buddy Guard’s iPhone and playing a siren sound.  In this prototype, the assumed use case is the Buddy Guard taps on the button that opens the prototype in the foreground.  The prototype simply displays the iBeacon values for proximity, accuracy, and rssi:

IMG 0032

The accuracy isn’t interesting for this prototype because it is used to determine among more than one iBeacon advertising the same packet, which one is the “best.”

iBeacon Gives the Prototype Proximity Info

Proximity is the important attribute.  As noted in the Apple SDK documentation:

The value in this property gives a general sense of the relative distance to the beacon. Use it to quickly identify beacons that are nearer to the user rather than farther away.

Here are the values as discussed in Apple’s iBeacon Getting Started document:

 

proximityRangeDefFromGettingStarted

There is no way to get positional information, i.e.: “go right, then go left and you’ll run into the person wearing the sling device.”  Rather, iBeacon with the proximity is more like the HOT/WARM/COLD game where an item is hidden.  A person looks for the item while the other players shout “HOT”, “WARM”, or “COLD” depending if the searcher is getting closer or farther away.  This may be useful.  This may be not.

Prototype Flow

(please download and view the code to follow along)

I added to the flow of the prototype:

  • a way for the View Controller to get a call back when the background app has received an alert.  The more I understand the MVC (Model-View-Controller) way of structuring an iOS app, the more sense and ease it is to separate out the model (in this case discovery of the alerts) with the View (displaying UI in the foreground)
  • The View Controller sets and updates location information by setting View properties.
I used Apple’s iBeacon Core Location framework to provide location information.  A great feature of the LightBlue Bean is it can send iBeacon formatted BLE packets.  I have hopes to use an iBeacon to indicate where the person being attacked is located.  This may not be possible.  Given what I have tested, iBeacon’s main scenario is retail in which a customer walks near a display and the iOS app displays contextual ads or information about what they are looking at.  In this way, I see iBeacon as augmenting reality.  
 
I implemented two classes:
  • IBeaconProximity: handles all iBeacon services.  All that is needed to get iBeacon parameters (proximity, accuracy, rssi) is to set the ViewController as a delegate of the BeaconDelegate protocol and implement the BeaconDelegate’s call back function beaconDidUpdate 
  • BTDiscovery: handles BLE discovery of the Bean peripheral.
The code seems fairly simple.  Because iBeacon does not work in the background, I use BLE discovery to find a sling device.  Once the device is found, a notification alert playing a loud siren sound is played.  The Buddy Guard taps on the notification and the sling app is in the foreground.  At this point, iBeacon packets are detected through the IBeaconProximity class and labels are updated when the view controller gets a beaconDidUpdate call back.
 
iBeacon

iBeacon Packets

I got overly interested in the contents of iBeacon packets and how they fit into BLE traffic when exploring how iBeacon’s proximity technology. I wanted to gain a better understanding of what can and can’t be done with iBeacon’s proximity information.

Here is what a BLE packet looks like:

BLEPacketFormat

In order to intercept a BLE packet and see take a peak at these fields, I installed Apple’s Packet Logger Utility.  Apple briefly discusses Packet Logger here.  I found the easiest way on a Mac to get to this utility is to option-shift while pushing the left mouse button on the BLE symbol.  

Pasted Image 1 13 15 5 32 AM

It can also be installed as an extension to XCode as discussed in Apple’s documentation.
I used this iBeacon scanning app to scan for iBeacon advertisements on my Mac.  My Bean was turned on and advertising iBeacon packets.

BLE Packet 

Here is a BLE packet I intercepted.
ScanAdvertisement

 

Interesting stuff:

  • event type: Scan Response
  • Local name: HELP
  • Mac address: D0:39:72:D3:44:19
  • TXPower: 4
  • RSSI: -72 dBm

What is TXPower?  As noted in this post about the Estimote iBeacon peripheral:

Broadcasting Power is the power with which the beacon broadcasts its signal, i.e. the power with which the signal leaves the beacon’s antenna. The owner of the beacon can change this setting e.g. using the Estimote app. The value ranges between -30 dBm and +4 dBm, lowest to highest power settings respectively. The higher the power, the bigger the beacon’s range and the more stable the signal, but it also shortens the battery life of the beacon—so you might want to consider lowering it to the minimum required by your use case.
 
A header file in the Bean’s iOS SDK has this enum:
 

typedef NS_ENUM(NSUInteger, PTDTxPower_dB) {

    /**

     *  -23db. Use this to maximize power savings.

     */

    PTDTxPower_neg23dB = 0,

    /**

     *  -6db

     */

    PTDTxPower_neg6dB,

    /**

     *  0db.

     */

    PTDTxPower_0dB,

    /**

     *  4db. This is the default value and maximum transmission strength.

     */

    PTDTxPower_4dB

};

So a TXPower of 4 means the Bean is transmitting at 4dB – perhaps harder on battery life, but better on signal strength.  A common trade off.

And RSSI?  From the same post:

RSSI is the strength of the beacon’s signal as seen on the receiving device, e.g. a smartphone. In general, the greater the distance between the device and the beacon, the lesser the strength of the received signal. Think: if you drop a stone into a container with water, the wave is bigger near the point of impact and smaller further away.

iBeacon Packet

In order for a peripheral to send out iBeacon packets, it has to support the iBeacon packet format.  

iBeaconPacketFormat

an iBeacon packet immediately followed the BLE Scan Response packet:

iBeaconPacket

The packet shows an iBeacon is a Connectable undirected advertising packet.  What gets interesting is decoding the data.  A SO article details the meaning.  Of interest:

  • ID: A4 95 12 34 C5 B1 4B 44 B5 12 13 70 F0 2D 74 DE
Aha!  Here is a line from the IBeaconProximity class within my Swift project:

let beaconUUIDString = “A4951234-C5B1-4B44-B512-1370F02D74DE”

the next two bytes are the major and minor id’s (part of the iBeacon specification).  

The last byte – 0XC5 – is the “measured power”.  Back to this post:

Measured Power is a factory-calibrated, read-only constant which indicates what’s the expected RSSI at a distance of 1 meter to the beacon.

But this calibration is only relative to what the environment was in the factory.  Note in Apple’s iBeacon Getting Started documentation:

…To provide the best user experience, it is critical to perform calibration in your deploymentenvironment. As each beacon is installed you should perform a calibration step….Combined with RSSI, this allows to estimate the actual distance between the device and the beacon…the physical surroundings can affect the signal strength. Since the surroundings will almost certainly vary between installation locations it is important to repeat these steps for each beacon that is installed.

The above is just more detail on the lack of precision in BLE/iBeacon distance/proximity prediction.

Things to Know about the XCode Environment.

I found the following tip extremely useful. At 31:10 into WWDC 2013 video session 406: Taking Control of Auto Layout in Xcode 5, the presenter shows a shortcut to getting a second window while doing a layout / working on code:

 
 

 

 

 

GettingToPreviewTool

then do option-shift when selecting the storyboard to

PreviewAssistantNavigator

About Protocols and Delegates

 This tutorial does a good job explaining coding protocols and delegates. 

Don’t Forget the Info.plist Keys!

To get Core Location code working ,  this key needs to be added to the  Info.plist file.

NSLocationAlwaysUsageDescription : "Some Description of why you want to take location"

And I’m Done…For Now…

I hope I remembered to document the important things.  The main “gotchas” I had was around keys required in info.plist….UIBackgroundModes and NSLocationAlwaysUsageDescription seem to be the most relevant for this prototype.

 

 

Thanks for reading this far.  Please find many things to smile about.

 

Advertisements