The CoreBluetooth namespace allows developers to work with Bluetooth Low Energy (Bluetooth LE) devices.
The Bluetooth LE model revolves around MonoTouch.CoreBluetooth.CBPeer objects. There are two kinds of MonoTouch.CoreBluetooth.CBPeer: MonoTouch.CoreBluetooth.CBCentral objects that scan and consume data provided by MonoTouch.CoreBluetooth.CBPeripheral objects that correspond to data-providing Bluetooth LE devices.
Generally, the iOS device will be in the MonoTouch.CoreBluetooth.CBCentral role, but it is also possible to create apps in which the device is a MonoTouch.CoreBluetooth.CBPeripheral.
The following example shows the typical initialization behavior of an app that consumes data from external Bluetooth LE devices. Applications that have a MonoTouch.CoreBluetooth.CBCentral must have an associated MonoTouch.CoreBluetooth.CBCentralManagerDelegate delegate object and must override it's MonoTouch.CoreBluetooth.CBCentralManagerDelegate.UpdatedState method. The override must check the state of the MonoTouch.CoreBluetooth.CBCentralManager and confirm that it is MonoTouch.CoreBluetooth.CBCentralManagerState.PoweredOn.
Typically, applications will want to scan for Bluetooth LE peripherals. This is a high-energy function, so developers should call MonoTouch.CoreBluetooth.CBManager.StopScan after finding the MonoTouch.CoreBluetooth.CBPeripheral in which they are interested or after a certain amount of time.
C# Example
public class MySimpleCBCentralManagerDelegate : CBCentralManagerDelegate { override public void UpdatedState (CBCentralManager mgr) { if (mgr.State == CBCentralManagerState.PoweredOn) { //Passing in null scans for all peripherals. Peripherals can be targeted by using CBUIIDs CBUUID[] cbuuids = null; mgr.ScanForPeripherals (cbuuids); //Initiates async calls of DiscoveredPeripheral //Timeout after 30 seconds var timer = new Timer (30 * 1000); timer.Elapsed += (sender, e) => mgr.StopScan(); } else { //Invalid state -- Bluetooth powered down, unavailable, etc. System.Console.WriteLine ("Bluetooth is not available"); } } public override void DiscoveredPeripheral (CBCentralManager central, CBPeripheral peripheral, NSDictionary advertisementData, NSNumber RSSI) { Console.WriteLine ("Discovered {0}, data {1}, RSSI {2}", peripheral.Name, advertisementData, RSSI); } } public partial class HelloBluetoothCSharpViewController : UIViewController { MySimpleCBCentralManagerDelegate myDel; public override void ViewDidLoad () { base.ViewDidLoad (); //Important to retain reference, else will be GC'ed myDel = new MySimpleCBCentralManagerDelegate (); var myMgr = new CBCentralManager (myDel, DispatchQueue.CurrentQueue); } //...etc... }
The MonoTouch.CoreBluetooth.CBCentralManagerDelegate.DiscoveredPeripheral method may be called multiple times for a single physical device. Once application developers have a reference to the MonoTouch.CoreBluetooth.CBPeripheral in which they are interested, they should maintain that reference for further work and call MonoTouch.CoreBluetooth.CBCentralManager.StopScan.
With a reference to a discovered MonoTouch.CoreBluetooth.CBPeripheral, developers can then connect to it, as shown in the following example.
A MonoTouch.CoreBluetooth.CBPeripheral has zero or more MonoTouch.CoreBluetooth.CBServices, each of which has zero or more MonoTouch.CoreBluetooth.CBCharacteristics. If the characteristic represents a measurement (such as a heartbeat, time, temperature, etc.), the value will be in the MonoTouch.CoreBluetooth.CBCharacteristic.Value property.
C# Example
public class SimplePeripheralDelegate : CBPeripheralDelegate { public override void DiscoveredService (CBPeripheral peripheral, NSError error) { System.Console.WriteLine ("Discovered a service"); foreach (var service in peripheral.Services) { Console.WriteLine (service.ToString ()); peripheral.DiscoverCharacteristics (service); } } public override void DiscoveredCharacteristic (CBPeripheral peripheral, CBService service, NSError error) { System.Console.WriteLine ("Discovered characteristics of " + peripheral); foreach (var c in service.Characteristics) { Console.WriteLine (c.ToString ()); peripheral.ReadValue (c); } } public override void UpdatedValue (CBPeripheral peripheral, CBDescriptor descriptor, NSError error) { Console.WriteLine ("Value of characteristic " + descriptor.Characteristic + " is " + descriptor.Value); } public override void UpdatedCharacterteristicValue (CBPeripheral peripheral, CBCharacteristic characteristic, NSError error) { Console.WriteLine ("Value of characteristic " + characteristic.ToString () + " is " + characteristic.Value); } } //... mgr = new CBCentralManager (myCentralDelegate, DispatchQueue.CurrentQueue); mgr.ConnectedPeripheral += (s, e) => { activePeripheral = e.Peripheral; System.Console.WriteLine ("Connected to " + activePeripheral.Name); if (activePeripheral.Delegate == null) { activePeripheral.Delegate = new SimplePeripheralDelegate (); //Begins asynchronous discovery of services activePeripheral.DiscoverServices (); } }; //Connect to peripheral, triggering call to ConnectedPeripheral event handled above mgr.ConnectPeripheral (myPeripheral);