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