RSSIで近くの端末に接続する
複数人でBluetooth通信のアプリを操作する際いろんなデバイスに繋がってしまい検証が困難になってしまいます。
AndroidのBluetoothにはMacIDが用意されているので自分の検証用端末のIDで絞れるのですが、iOSのBleutoothにMacIDは存在しません。
そのためiOSで端末を制御する際はRSSIを使って電波強度の強いものに接続するのが良いです。※電波強度==距離ではありません
RSSIとは
RSSIは-の値で取得することができます。0に近いほど電波強度が強いようです。
RSSIは、主に無線LANやBluetoothなどの無線通信において、送信範囲の制御などの目的で利用されている。これは、あまりに出力が強いと不必要に距離の離れた箇所までカバーすることになり、電力の無駄や盗聴の危険性が生じるためである。
https://www.weblio.jp/content/RSSI
信号強度は以下のような感じらしいです。-30が最高で-90がかなり弱いノイズのような値らしいです。
検証している過程で-25、-95の値を取得したので限界値が-30, -90というわけではないようです。
信号強度 | TL;DR | 説明 | 必須 |
-30 dBm | 素晴らしい | 達成可能な最大信号強度。クライアントは、これを実現するには、APから僅か数フィートである必要があります。現実的には一般的ではなく、望ましいものでもありません | N/A |
-67 dBm | 良好 | 非常に信頼性の高く、データパケットのタイムリーな伝送を必要とするアプリケーションのための最小信号強度 | VoIP/VoWiFi, ストリーミングビデオ |
-70 dBm | Okay | 信頼できるパケット伝送に必要な最小信号強度 | Email, web |
-80 dBm | よくない | 基本的なコネクティビティに必要な最小信号強度。パケット伝送は信頼できない可能性があります | N/A |
-90 dBm | 使用不可 | ノイズレベルに近いかそれ以下の信号強度。殆ど機能しない | N/A |
引用: https://www.ibsjapan.co.jp/tech/details/metageek-solution/understanding-rssi.html
コード
スキャンしてペリフェラルを発見すると呼ばれるfunc centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,advertisementData: [String : Any],rssi RSSI: NSNumber)メソッドの引数としてRSSIを保持しています。
RSSIをラベルに表示する小さなアプリをさくせいしました。デバイスを指定しないと物凄い数のペリフェラルを検出してしまうため、検証デバイスとしてtoio core cubeを使用しました。
通常の設定では同じデバイスを重複して取得しないようになっていますが、scanForPeripheralsのoption, CBCentralManagerScanOptionAllowDuplicatesKeyの値をtrueに設定することで同じデバイスを何度も取得することができます。
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBCentralManagerDelegate {
@IBOutlet weak var label: UILabel!
var manager : CBCentralManager!
override func viewDidLoad() {
super.viewDidLoad()
manager = CBCentralManager(delegate: self, queue: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
central.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey : true])
}
}
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any],
rssi RSSI: NSNumber) {
if peripheral.name != "toio Core Cube"{
return
}
print(RSSI)
label.text = String(Int(truncating: RSSI))
}
}
電波強度が-50以下でない場合returnする処理を記述しておけば同じ部屋で開発を行っていてもある程度は自分のデバイスに繋がるようになります!
検証動画
スキャンを行なっているデバイスを名前で絞って一件のみにし、デバイスを近づけたり遠ざけたりしています。-30付近の値が表示される際はiPhoneの真上にデバイスがいる時です。
広い敷地があればBluetoothデバイスをたくさん配置して、迷路や謎解きゲームなんかに使えそうだなと思いました。