iPhone/iPadスマートアプリ開発レシピ
iPhone/iPadスマートアプリ開発レシピ(4)

iPhoneアプリでBluetooth通信を使うための基礎知識


クラスメソッド株式会社
開発部 掛川敦史
2012/6/19

Core Bluetoothを使ったアプリの実装


CBCentralManager

 CBCentralManagerは、Bluetooth LEに対応するデバイスの検索や接続処理などを行うコンポーネントです。デバイスの検索処理の結果や接続状態の変化などは、CBCentralManagerDelegateプロトコルに適合するデリゲートでハンドルすることになります。

 CBCentralManagerを作成する部分のコードです。

centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
- PR -

 initWithDelegate:queue:メソッドでデリゲートを指定して生成しています。queueパラメータは、デリゲートメソッドが呼び出されるスレッドをdispatch queueで指定します。nilを指定した場合、メインスレッドのdispatch queueが自動的に選択されます。

Bluetooth LE対応デバイスの探索

 iOSデバイスはBluetooth Smart Readyデバイス側なので、アドバタイズしているデバイスを探索することになります。その際はCBCentralManagerのscanForPeripheralsWithServices:options:メソッドを利用します。以下は、CBCentralMangerでデバイスを探索する部分のコードです。

// 探索対象のデバイスが持つサービスを指定
NSArray *services = [NSArray arrayWithObjects:[CBUUID UUIDWithString:kUUIDServiceImmediateAlert],
                     [CBUUID UUIDWithString:kUUIDServiceBatteryService], nil];
// 単一デバイスの発見イベントを重複して発行させない
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]
                                                    forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
// デバイスの探索を開始
[centralManager scanForPeripheralsWithServices:services options:options];

 scanForPeripheralsWithServices:options:メソッドの最初のパラメータは、探索対象のデバイスを絞り込むためのものです。このパラメータで渡したサービスに対応しているデバイスのみが探索対象です。

 GATTプロファイルの仕様では、各サービスやキャラクタリスティックなどを識別するためにUUIDが割り当てられており、サービスの指定はUUIDを表すCBUUIDクラスのインスタンスの配列によって行います。このパラメータにnilをセットすることにより探索対象を制限しないようにできますが、この方法は推奨されていません。

 今回のサンプルアプリでは、Immediate AlertサービスのUUIDである「1802」と、Battery ServiceサービスのUUIDである「180F」を探索対象サービスのUUIDとして指定しています。

 optionsパラメータには、NSDictionaryにデバイス探索時のオプションをセットして渡しています。このパラメータで、CBCentralManagerScanOptionAllowDuplicatesKeyを「YES」に設定した場合、探索対象のサービスをアドバタイズしているデバイスが見つかるたびにデバイスの発見をCBCentralMangerのデリゲートに通知します。「NO」に設定した場合は、探索対象のサービスをアドバタイズしているデバイスが見つかると、CBCentralMangerのデリゲートに通知します。複数の探索対象サービスで同一のデバイスを発見した場合は、CBCentralMangerのデリゲートへの通知が1回にまとめられます。

 このサンプルでは、Immediate AlertサービスとBattery Serviceサービスが同一デバイスに搭載されていることを前提としていますので、CBCentralManagerScanOptionAllowDuplicatesKeyをNOに設定して、同一デバイス発見の通知が1回のみになるようにしています。

デバイスの発見と接続

 デバイスが発見されると、CBCentralManagerDelegateのcentralManager:didDiscoverPeripheral:advertisementData:RSSI:メソッドが呼び出されます。以下は、メソッド内の処理です。

- (void)centralManager:(CBCentralManager *)central
 didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary *)advertisementData
                  RSSI:(NSNumber *)RSSI
{   
    targetPeripheral = peripheral;
    peripheral.delegate = self;
   
    // 発見されたデバイスに接続
    if (!peripheral.isConnected)
    {
        [centralManager connectPeripheral:peripheral options:nil];
    }
}

 CBPeripheralはデバイスを表すクラスです。peripheralパラメータには、発見されたデバイスに対応するCBPeripheralのインスタンスがセットされています。デバイス間で通信を行う際は、CBPeripheralのインスタンスを利用するので、参照をクラスの変数に格納しておきます。

 また、CBPeripheralの処理結果や状態の変化時は、CBPeripheralDelegateプロトコルに適合したデリゲートでハンドルすることになるので、CBPeripheralのインスタンスにデリゲートを指定しておきます。

 そのほか、advertisementDataパラメータは発見されたデバイスの情報がNSDictionary型で格納されており、RSSIには信号強度がNSNumber型で格納されています。

 デバイスが発見された場合は続けて接続処理を行います。発見されたデバイスとの接続処理は、CBCentralManagerのconnectPeripheral:options:メソッドで行います。

デバイスの接続とサービスの探索

 デバイスの接続が完了するとCBCentralManagerDelegateのcentralManager:didConnectPeripheral:メソッドが呼び出されます。また、デバイスの接続に失敗した場合は、CBCentralManagerDelegateのcentralManager:didFailToConnectPeripheral:error:メソッドが呼び出されます。以下は、centralManager:didConnectPeripheral:メソッド内の処理です。

- (void)centralManager:(CBCentralManager *)central
  didConnectPeripheral:(CBPeripheral *)peripheral
{   
    // 外部デバイスとの接続完了を通知
    [self.delegate peripheralManagerDidConnectPeripheral:self];
   
    // 探索するサービスを指定
    NSArray *services = [NSArray arrayWithObjects:[CBUUID UUIDWithString:kUUIDServiceImmediateAlert],
                         [CBUUID UUIDWithString:kUUIDServiceBatteryService], nil];
    // サービスの探索を開始
    [peripheral discoverServices:services];
}

 必要があればUIの更新処理を行い、次に、接続したデバイスに搭載されているサービスの探索を行います。サービスの探索は、CBPeripheralのdiscoverServicesメソッドで行います。パラメータで渡しているサービスのUUIDの配列は、CBCentralManagerのscanForPeripheralsWithServices:options:メソッドの場合と同様に探索するサービスを指定するものです。

 ここでも、サービスを指定せずnilをセットできますが、こちらもまた非推奨です。これはキャラクタリスティックやディスクリプタの探索時も同様です。

サービスの発見とキャラクタリスティックの探索

 サービスが発見されるとCBPeripheralDelegateのperipheral:didDiscoverServices:が呼び出されます。

- (void)peripheral:(CBPeripheral *)peripheral
didDiscoverServices:(NSError *)error
{
    if (error)
    {
        NSLog(@"didDiscoverServices error: %@", error.localizedDescription);
        return;
    }
   
    if (peripheral.services.count == 0)
    {
        NSLog(@"didDiscoverServices no services");
        return;
    }
   
    for (CBService *service in peripheral.services)
    {
        if ([service.UUID isEqual:[CBUUID UUIDWithString:kUUIDServiceImmediateAlert]])
        {
            // Immediate Alertサービスを発見した場合、Alert Levelキャラクタリスティックの探索を開始
            [peripheral discoverCharacteristics:[NSArray arrayWithObjects:[CBUUID UUIDWithString:kUUIDCharacteristicsAlertLevel], nil] forService:service];
        }
        else if ([service.UUID isEqual:[CBUUID UUIDWithString:kUUIDServiceBatteryService]])
        {
            // Battery Serviceサービスを発見した場合、Battery Levelキャラクタリスティックの探索を開始
            [peripheral discoverCharacteristics:[NSArray arrayWithObjects:[CBUUID UUIDWithString:kUUIDCharacteristicsBatteryLevel], nil] forService:service];
        }
    }
}

 サービス探索時にエラーがあった場合はerrorパラメータにエラーがセットされます。

 CBServiceはサービスを表すクラスです。ここでは、探索したサービスの中から目的のImmediate AlertサービスとBattery Serviceサービスを探しています。サービスが見つかった場合、Immediate Alertサービスに対してはAlert Levelキャラクタリスティックの、Battery Serviceサービスに対してはBattery Levelキャラクタリスティックの探索を行っています。

 キャラクタリスティックの探索はCBPeripheralのdiscoverCharacteristics:forService:メソッドで行います。1番目のパラメータは探索したいキャラクタリスティックをUUIDの配列で指定し、2番目のパラメータは探索対象のサービスをCBServiceのインスタンスで指定します。

 なお利用するサービスによっては、入れ子のサービスを持っている場合があります。今回は行いませんが、入れ子のサービスを探索する場合はCBPeripheralのdiscoverIncludedServices:forService:を呼び出します。

 続いて次ページでは、サンプルアプリを完成させ実行します。

1-2-3-4

 INDEX
iPhone/iPadスマートアプリ開発レシピ(4) 
iPhoneアプリでBluetooth通信を使うための基礎知識
  Page1
意外と知らない? 「Bluetooth」は3種類ある
Bluetooth LE対応機器
iOSデバイスのBluetooth対応状況
「Game Kit」によるBluetooth通信
Game Kitを使ったアプリの実装
  Page2
「Core Bluetooth」によるBluetooth LE通信
Page3
Core Bluetoothを使ったアプリの実装
  Page4
Bluetoothでスマホは生活に欠かせないものに



 Smart&Social フォーラム トップページへ



Smart & Social フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Smart & Social 記事ランキング

本日 月間