Building the Application
For this project, you'll build an iOS 8 application using Apple's Xcode 6. Follow these steps:
- Create a single view application and name it SensorTag.
Drag-and-drop three images to the Supporting Files group of the project (see Figure 2). The images contain one red and one blue button, as well as an image to represent the button being pressed (you can find the images in the source code download of this project):
Figure 2
Adding images to the project.
Select the Main.Storyboard file in the project to edit it in the Storyboard Editor. Populate the View window with the following views (see Figure 3):
- Button (set the title to Scan for SensorTag).
- Button (Custom type; the first button loaded with the redbutton.jpeg image, and the second button loaded with the bluebutton.jpeg image).
- Label.
Figure 3
Adding views to the View window.
Select the red button and change its State Config attribute to Selected (see Figure 4). Then set its Image attribute to buttonpressed.png. Doing so causes the button to change its image when the state has been changed from default to selected (when the button is tapped), creating the visual effect that it has been “pressed.” Repeat this step for the blue button.
Creating the Outlets and Action for the Views
In Xcode, create the outlets and action for the various views that you have just added to the View window. The outlets and action code should look like this:
import UIKit class ViewController: UIViewController { @IBOutlet weak var btnLeft: UIButton! @IBOutlet weak var btnRight: UIButton! @IBOutlet weak var txtStatus: UILabel! @IBAction func btnScan(sender: AnyObject) { }
Importing the CoreBluetooth Framework
The CoreBluetooth Framework in the iOS software development kit provides the APIs for connecting to Bluetooth LE devices. To connect to the SensorTag, you first need to import the CoreBluetooth Framework into your project.
Select the project name in Xcode and select the Build Phases tab on the right. Go to the Link Binary with Libraries section and click the plus (+) button. Select CoreBluetooth.framework and click Add ( see Figure 5).
Scanning for the SensorTag
To connect to the SensorTag, you need to make it advertise its presence. To do so, tap the Pairing button on the side of the SensorTag; the LED in the front will start blinking.
The application needs to use the CoreBluetooth APIs to connect to the SensorTag (known as a peripheral in Bluetooth LE-speak). Add the following code (shown in bold) to the ViewController.swift file:
import UIKit import CoreBluetooth class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate { @IBOutlet weak var btnLeft: UIButton! @IBOutlet weak var btnRight: UIButton! @IBOutlet weak var txtStatus: UILabel! //---store the connected Ti SensorTag as a CBPeripheral object--- var connectedSensorTag: CBPeripheral! //---the CBCentralManager object helps to scan for peripherals--- var centralManager: CBCentralManager! @IBAction func btnScan(sender: AnyObject) { //---scan for peripheral devices--- self.centralManager.scanForPeripheralsWithServices(nil, options:nil) } override func viewDidLoad() { super.viewDidLoad() //---create an instance of the CBCentralManager class and set the // delegate to self--- self.centralManager = CBCentralManager(delegate: self, queue: nil) } //---this function is fired whenever there is a change in the // CBCentralManager--- func centralManagerDidUpdateState(central: CBCentralManager!) { println("centralManagerDidUpdateState:") switch (central.state) { case .PoweredOff: println("CBCentralManagerStatePoweredOff") case .Resetting: println("CBCentralManagerStateResetting") case .PoweredOn: println("CBCentralManagerStatePoweredOn") //---scan for peripheral devices--- self.centralManager.scanForPeripheralsWithServices(nil, options:nil) case .Unauthorized: println("CBCentralManagerStateUnauthorized") case .Unsupported: println("CBCentralManagerStateUnsupported") default: println("CBCentralManagerStateUnknown") } } //---fired when peripheral devices are found--- func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI: NSNumber!) { //---print out the name of the scanned peripheral--- println("Discovered \(peripheral.name)") //---print out the UUID of the scanned peripheral--- //---you can save this value so that next time you can reconnect back // to it--- println("NSUUID string \(peripheral.identifier.UUIDString)") //---as long as you find one SensorTag, stop the scanning--- var range = (peripheral.name as NSString).rangeOfString("Sensor") if (range.location != NSNotFound) { connectedSensorTag = peripheral //---stop the scanning--- self.centralManager.stopScan() } }
Deploy the application onto a real iOS device and tap the Scan for SensorTag button. Ensure that the SensorTag is advertising. In the Output window, observe the following when the device manages to discover the SensorTag:
centralManagerDidUpdateState: CBCentralManagerStatePoweredOn Discovered TI BLE Sensor Tag
NSUUID string AFAAAFD7-0573-3B76-4202-031393542B15
Each Bluetooth LE device has a UUID string that uniquely identifies the peripheral. In a real-life application, you might want to save this UUID so that the next time you scan for the same SensorTag, you could use this identifier to find the SensorTag.
Connecting to the SensorTag
When the SensorTag has been discovered, you should connect to it so that you can query it for services and characteristics. Find this method:
centralManager:didDiscoverPeripheral:advertisementData:RSSI:
Add the following code in bold to the method:
//---fired when peripheral devices are found--- func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI: NSNumber!) { //---print out the name of the scanned peripheral--- println("Discovered \(peripheral.name)") //---print out the UUID of the scanned peripheral--- //---you can save this value so that next time you can reconnect back // to it--- println("NSUUID string \(peripheral.identifier.UUIDString)") //---as long as you find one SensorTag, stop the scanning--- var range = (peripheral.name as NSString).rangeOfString("Sensor") if (range.location != NSNotFound) { connectedSensorTag = peripheral //---stop the scanning--- self.centralManager.stopScan() //---save the peripheral--- //---connect to the peripheral--- self.centralManager.connectPeripheral(peripheral, options:nil) self.txtStatus.text = "Connected!" } }
Add the following method to the ViewController class so that it can be fired when a peripheral is connected:
func centralManager(central: CBCentralManager!, didConnectPeripheral peripheral: CBPeripheral!) { println("Peripheral connected: \(peripheral.name)") peripheral.delegate = self }
Deploy the application onto the device again. When the SensorTag is successfully connected (see Figure 6), the following code will appear in the Output window:
centralManagerDidUpdateState: CBCentralManagerStatePoweredOn Discovered TI BLE Sensor Tag
NSUUID string AFAAAFD7-0573-3B76-4202-031393542B15
Peripheral connected: TI BLE Sensor Tag
Figure 6
The label shows the connection status.
Add the following method to the ViewController class so that it can be fired if the SensorTag is disconnected from your device for some reason:
func centralManager(central: CBCentralManager!, didDisconnectPeripheral peripheral: CBPeripheral!, error: NSError!) { if connectedSensorTag == peripheral { self.txtStatus.text = "Disconnected!" } }