REBL600FRを検知
引き続き、REBL600FRを用いて遊んでみたいと思います。
前回のREBL600FRをiBeaconとして検知してみた!では既存のアプリを拝借してREBL600FRを検知していました。
今回はそこを自作してみたいと思います。
そのためにCoreBluetooth.frameworkを使います。
まずは、REBL600FRの発信するBLEを検知してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
上記ソースの説明をします。
1でCBCentralManagerを初期化すると、centralManagerDidUpdateStateメソッドが呼び出されます。
そこで、Centralとして機能する(BluetoothがONで正常である)場合に限り、scanForPeripheralsWithServicesメソッドを実行することでPeripheralのスキャンを開始します。
今回は、scanForPeripheralsWithServicesのserviceUUIDsとoptionsをnilにしています。
もし、あらかじめスキャンしたいBLEのUUIDが決まっているのであれば、
1
| |
といったように指定してあげましょう。
※ nilの指定は非推奨とされています。
また、optionsにはCBCentralManagerScanOptionAllowDuplicatesKeyとCBCentralManagerScanOptionSolicitedServiceUUIDsKeyを指定可能となっています。
CBCentralManagerScanOptionAllowDuplicatesKeyを明示的指定しない場合はデフォルトNOと判断されます。
YESにした場合、Peripheralからアドバタイズパケットを受信する度にペリフェラル発見通知が実行されます。
CBCentralManagerScanOptionSolicitedServiceUUIDsKeyにはスキャンしたいUUIDの配列を指定できます。
servicesで既に指定しているので、実際のところ何が違うのでしょうか…。
続いての実装です。
1 2 3 4 5 6 7 8 9 10 | |
scanForPeripheralsWithServices実行後にPeripheralを発見した場合、didDiscoverPeripheralメソッドが呼び出されます。
このメソッドでは、advertisementDataとRSSIの値を取得できます。
では、実際に取得できる値を見てみましょう。
scanForPeripheralsWithServicesが実行された後に、REBL600FRのスイッチをONにします。

すると、
1 2 3 4 5 6 7 | |
と値を取得できました。
kCBAdvDataChannelはBLEデバイスの発見と接続に利用するアドバタイズメントチャネルのことで、kCBAdvDataIsConnectableは接続可能なPeripheralかどうか判別する値(1であれば接続可)で、kCBAdvDataLocalNameはPeripheralの名前のことです。
AppleのCBCentralManagerDelegate Protocol Referenceを見ると、advertisementDataには他にも取得可能な値が入っていることがあるようです。
REBL600FRに接続
次に、先ほど発見することができたREBL600FRに接続してみたいと思います。
didDiscoverPeripheralが実行されたときに検知したperipheralに接続するようにしてみます。
1 2 3 4 5 6 7 8 9 10 11 | |
connectPeripheralメソッドで接続したいPeripheralに接続することができます。
このときoptionsにはCBConnectPeripheralOptionNotifyOnConnectionKey, CBConnectPeripheralOptionNotifyOnDisconnectionKey, CBConnectPeripheralOptionNotifyOnNotificationKeyの3種類のいずれかを指定可能です。
それぞれ、Peripheralと接続, Peripherlと切断, PeripheralからNotificationを受信した場合にアラートを表示したい場合に指定します。
接続が確立された場合にcentralManager:didConnectPeripheral:メソッドが呼び出されます。
この中で、Peripheralが提供するサービスを検索する処理を書いてみましょう。
1 2 3 4 5 6 7 8 9 | |
電池の消耗を防ぐために、接続が確立された後はPeripheralのスキャンを停止します。
discoverServicesメソッドでPeripheralのサービスを検索します。
引数には検索したいサービスのUUIDの配列を指定可能です。
nilにした場合は全てのサービスを検索します。こちらもnilの指定は非推奨とされています。
サービスが見つかると、didDiscoverServices:メソッドが呼び出されます。
そこでさらに、サービスが持っているキャラクタリスティックを検索します。
1 2 3 4 5 6 7 8 9 10 11 12 | |
キャラクタリスティックの検索はdiscoverCharacteristics:メソッドを使います。
例によって、引数のcharacteristicUUIDsはnilを指定することで、全てのキャラクタリスティックを検索しています。
もちろんnilは非推奨とされています。
今回は取得できた全てのサービスに対して、全てのキャラクタリスティックを検索するため、上記のようにfor文を使っています。
キャラクタリスティックが見つかると、didDiscoverCharacteristicsForService:メソッドが呼び出されます。
1 2 3 4 5 6 7 8 9 10 | |
setNotifyValueはキャラクタリステックの値が変わったときにdidUpdateNotificationStateForCharacteristic:error:を呼び出すためにYESで設定しています。
readValueForCharacteristic:メソッドは検索して見つかったキャラクタリステックの値を読むために実行しています。
因みに、CBCharacteristicクラスはプロパティにpropertiesを持っています。
これは、そのデータが Read Only なのか Read and Write なのかを判別するために利用します。
REBL600FRの場合、characteristicsをNSLogでログ出力してみると、
1 2 3 4 5 | |
となりました。
CBCharacteristic Class Referenceを見ると、0x2はCBCharacteristicPropertyReadとされていますが、0xAは該当するものが記載されていませんでした。
キャラクタリステックの値の取得が完了すると、didUpdateValueForCharacteristic:error:メソッドが呼ばれます。
1 2 3 4 5 | |
これで各パラメータの値が確認できました。
気をつけたいのは、major, minor, Tx PowerなどはUTF8でエンコードをかけると文字化けしたログを吐くので、どんな値か見たい場合はエンコードせずにNSDataの値のまま見てみましょう。
う〜ん。今回は時間切れですね…。
次回はREBL600FRのパラメータをiPhoneから書き換えることにチャレンジしたいと思います。
といったところで本日はここまで。
ソースはパラメータの書き換えが完了したタイミングでGitHubにアップしたいと思います。
参考:
CoreBluetoothで出来る事
Bluetooth Low Energy(BLE)/ iBeaconとは
Reinforce-Lab’s Blog