iOSでのBluetooth通信入門 :CoreBluetooth プログラミングガイド 解説 :リモートのペリフェラルとのやり取りに関するベストプラクティス

bluetooth-ios_001

目次 > リモートのペリフェラルとのやり取りに関するベストプラクティス

Apple「CoreBluetoothプログラミングガイド」+独自解説


リモートのペリフェラルとのやり取りに関するベストプラクティス

Core Bluetoothフレームワークを導入すれば、アプリケーションはセントラル側のさまざまなトランザクションを、容易に実装できるようになります。とは言え、ペリフェラルの検出や接続、リモートのペリフェラルが持つデータの調査や読み書きなど、セントラルとしてのさまざまなタスクを、的確に制御できるようにしなければなりません。この章では、特にiOSデバイス用アプリケーションについて、的確な制御のために考慮するべきガイドラインやベストプラクティスを紹介します。

電波の使い方や電池の寿命に注意を払う

BLE機器とやり取りするアプリケーションを開発する際には、通信のために電波信号を送出していることを意識してください。ほかの種類の無線通信(Wi-Fi、旧式のBluetooth、同じBLEを使う他のアプリケーションなど)が、同じ周波数帯域を使っているかも知れないので、電波の送出は必要最小限にしなければなりません。
これはiOSデバイス用アプリケーションの場合特に重要です。電池の寿命にも大きく影響するからで
す。節度を持って電波を利用するためにも、以下のガイドラインに従ってください。結果的に、アプリケーションの性能が向上し、電池の寿命を延ばすことにも役立つでしょう。

デバイスの走査は必要な場合にのみ行う

セントラルは、CBCentralManagerクラスのscanForPeripheralsWithServices:options:メソッド
で、サービスをアドバタイズしているリモートのペリフェラルを検出するわけですが、これは明示的に停止されるまで続きます。
接続先が見つかり、さらに検出する必要がないのであれば、走査を停止してください。これは
CBCentralManagerクラスのstopScanメソッドで行います(“検出したペリフェラルに接続する” 。

必要がなければCBCentralManagerScanOptionAllowDuplicatesKeyオプションを指定しない

リモートのペリフェラルは、1秒間に複数のアドバタイズパケットを送出して、自身の存在を知らし
めようとすることがあります。デバイスを走査するscanForPeripheralsWithServices:options:メソッドは通常、ペリフェラルを繰り返し検出しても、1件の検出イベントにまとめてしまいます。すなわち、セントラルマネージャはデリゲートオブジェクトのcentralManager:didDiscoverPeripheral:advertisementData:RSSI:メソッドを、届いたアドバタイズパケットの数にかかわらず、新たにペリフェラルを検出するごとに1回だけ呼び出します。また、検出済みのペリフェラルであっても、アドバタイズの内容が変化した場合にはこのデリゲートメソッドを呼び出します。

scanForPeripheralsWithServices:options:メソッドに、走査オプションとして
CBCentralManagerScanOptionAllowDuplicatesKey定数を指定することにより、この動作を変更で
きます。ペリフェラルからアドバタイズパケットが届く都度、検出イベントが生成されるようになるのです。状況によってはこれが有用です。ペリフェラルまでの距離(受信信号強度、RSSI(ReceivedSignal Strength Indicator))に基づいて、接続するか否かを判断するような場合です。しかしながら、電池の寿命やアプリケーション性能に悪影響があるかも知れません。本当に必要な状況でのみ指定するようにしてください。

ペリフェラルのデータを的確に調査する

アプリケーションにとって当面関心のないサービスや特性も、ペリフェラルは提供しているかも知れません。サービスや特性をすべて検出しようとすると、電池の寿命や処理性能に悪影響があります。本当に必要なサービスや特性のみ検出するようにしてください。
たとえば、多くのサービスを提供するペリフェラルに接続しているけれども、アプリケーションが実際に必要とするのは2つだけであるとしましょう。この場合、該当する2つだけを検出することができます。次のように、サービスのUUID(CBUUIDオブジェクトで表される)の配列を、CBPeripheralクラスのdiscoverServices:メソッドに渡してください。

 [peripheral discoverServices:@[firstServiceUUID, secondServiceUUID]];

関心のある2つのサービスを検出した後、同様にして、関心がある特性のみを検出できます。(サー
ビスごとに)該当する特性を表すUUIDの配列を、CBPeripheralクラスの
discoverCharacteristics:forService:メソッドに渡してください。

 頻繁に変化する特性については、値の変化を通知するよう申し込む

“特性の値を取得する” (19 ページ)で説明したように、特性値を取得する方法は2つあります。

● 明示的にポーリングして特性値を取得する方法。必要の都度、readValueForCharacteristic:
メソッドを呼び出します。
● 特性値が変化する都度、通知を送るよう申し込む方法。1回だけsetNotifyValue:forCharacteristic:メソッドを実行します。

特に特性値が頻繁に変化する場合、できるだけ後者の方法を使うとよいでしょう。具体的な手順については“特性の値が変化したときに通知するよう申し込む” (20 ページ)を参照してください。

必要なデータがすべて得られたら切断する

接続の必要がなくなり次第すぐに切断すれば、電波の使用を抑制できます。次のような場合には切断してください。

● 通知を申し込んでいるどの特性についても、通知が届かなくなったとき(通知が届いているか否かは、当該特性のisNotifyingプロパティで確認可)。
● 必要なデータがすべて揃ったとき。

いずれの場合も、通知の申し込みを取り消してから切断してください。取り消しは、第1引数をNOとしてsetNotifyValue:forCharacteristic:メソッドを呼び出すことにより行います。ペリフェラルとの接続切断は、次のように、CBCentralManagerクラスのcancelPeripheralConnection:メソッドで行います。

 [myCentralManager cancelPeripheralConnection:peripheral];

 注意: cancelPeripheralConnection:メソッドは非ブロック型であり、CBPeripheralクラスのコマンド(切断しようとしているペリフェラルに対するもの)で保留状態のものは、実行を停止するかどうか分かりません。他のアプリケーションがまだ接続しているかも知れないので、ローカル接続を取り消しても、物理リンクが即座に切断されるとは限りません。
しかし当該アプリケーションに関する限り、切断されたと看做してよい状態になるので、セントラルマネージャは、デリゲートオブジェクトのcentralManager:didDisconnectPeripheral:error:メソッドを呼び出します。

 ペリフェラルに再接続する

Core Bluetoothフレームワークには、ペリフェラルに再接続する方法が、次のように3つあります。

● 既知のペリフェラル(これまでに検出または接続したもの)のリストを
retrievePeripheralsWithIdentifiers:メソッドで取得し、該当するペリフェラルがこの中にあれば接続を試みる方法。詳しくは“既知のペリフェラルのリストを取得する” で説明します。
● システムに接続されているペリフェラルのリストをretrieveConnectedPeripheralsWithServices:メソッドで取得し、該当するペリフェラルがこの中にあれば、アプリケーションに(ローカルに)接続する方法。詳しくは“接続済みペリフェラルのリストを取得する” で説明します。
● メソッドで走査してペリフェラルを検出し、見つかったら接続する方法。詳しくは“アドバタイズしているペリフェラルを検出する” および“検出したペリフェラルに接続する” (17 ページ)を参照してください。

 用途にもよりますが、再接続の都度、同じペリフェラルを走査、検出するのは、あまり望ましくないでしょう。まずは別の方法で再接続を試みてください。図 5-1のように、上述の順に試すというのもひとつの方法です。

図 5-1 再接続処理の流れの例

図5-1再接続処理の流れ
図5-1再接続処理の流れ

注意: アプリケーションの用途によって、試みるべき方法とその順序は違うかも知れません。第1の方法はまったく試みない、第1と第2の方法を並行して試みる、などの流れも考えられます。

既知のペリフェラルのリストを取得する

システムは初めて検出したペリフェラルに対して、識別子(NSUUIDオブジェクトで表されるUUID)を生成します。この識別子を(たとえばNSUserDefaultsクラスのリソースを使って)保存しておけば、後でこれを使って、CBCentralManagerクラスのretrievePeripheralsWithIdentifiers:メ
ソッドで再接続できます。以下、このメソッドを使って、一度接続したことがあるペリフェラルに再接続する方法を示します。
アプリケーションの起動時に、これまでに検出、接続し(、その識別子を保存しておい)たペリフェラルの識別子をまとめた配列を渡して、次のようにretrievePeripheralsWithIdentifiers:メソッ
ドを実行します。

 knownPeripherals =

[myCentralManager retrievePeripheralsWithIdentifiers:savedIdentifiers];

セントラルマネージャは、指定された識別子を、過去に検出したペリフェラルの識別子と照合し、その結果をCBPeripheralオブジェクトの配列として返します。ひとつも合致しなければ配列は空なので、ほかの方法を試みることになります。そうでなければ、(適当なUIを設けて)再接続先をユーザが選択できるようにしてください。
ユーザがペリフェラルを選択したら、CBCentralManagerクラスのconnectPeripheral:options:メ
ソッドで接続を試みます。接続が可能であれば、セントラルマネージャはデリゲートオブジェクトのcentralManager:didConnectPeripheral:メソッドを呼び出します。この時点でペリフェラルは、
再接続された状態になっています。

注意: 何らかの理由で、ペリフェラルに接続できないこともあります。たとえば、セントラルから離れたところに移動してしまっているかも知れません。さらに、BLE機器によっては、アドレスが定期的に、ランダムに変わります。すぐ近くにあったとしても、システムが検出した時点以降にアドレスが変わっていれば、接続しようとしているCBPeripheralオブジェクトと実際のペリフェラルが対応しないことになります。これが原因で再接続できなかった場合、改めてscanForPeripheralsWithServices:options:メソッドで検出しなければなりません。
ランダムに変わるアドレスについて詳しくは、Bluetooth 4.0仕様のVolume 3、Part C、Section10.8および「Bluetooth Accessory Design Guidelines for Apple Products」を参照してください。

接続済みペリフェラルのリストを取得する

ペリフェラルに再接続するもうひとつの方法として、当該ペリフェラルが(たとえば他のアプリケーションによって)システムに接続済みでないか調べる、というものがあります。これは
CBCentralManagerクラスのretrieveConnectedPeripheralsWithServices:メソッドで行います。
戻り値は、接続済みペリフェラルを表すCBPeripheralオブジェクトの配列です。
複数のペリフェラルが接続されているかも知れないので、(サービスのUUIDを表す)CBUUIDオブジェクトの配列を引数として渡します。システムに接続済みで、かつ、指定したサービスを提供するペリフェラルのみ取得できます。該当するペリフェラルがなければ配列は空なので、ほかの方法を試みることになります。そうでなければ、(適当なUIを設けて)再接続先をユーザが選択できるようにしてください。
ユーザがペリフェラルを選択したら、CBCentralManagerクラスのconnectPeripheral:options:メ
ソッドで、当該アプリケーションにローカルに接続します(システムには接続済みでも、アプリケーションと接続しなければデータのやり取りはできません)。ローカルな接続が確立すると、セントラルマネージャはデリゲートオブジェクトのcentralManager:didConnectPeripheral:メソッドを呼び出します。この時点でペリフェラルは、再接続された状態になっています。

 


※ このコンテンツはアップル社の提供する「CoreBluetoothプログラミングガイド」というPDFをwebの形式に変換したものをベースとしています。ページ中に含まれる図やテキストは「CoreBluetoothプログラミングガイド」からの引用が多く含まれます。PDFの形式ではなくウェブの形式で閲覧したい方への利便性を高めることや、「CoreBluetoothプログラミングガイド」だけではわかりにくいという箇所の捕捉を行うことが当コンテンツの主旨です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です