私はBluetoothLEセンサーデバイスに取り組んでいます。そのために、1対多のデータブロードキャストを形成する必要があります。仕様によると、周辺機器のマスターは1つしかなく、設計しているチップとスタックの制限により、マスターは3つのスレーブしか持つことができません。私が理解していることから、AndroidはとにかくBLEスレーブになることができないので、マスターとして私のデバイスを持つことはオプションではありません。
BT4仕様とメーカーのドキュメントの両方で、ブロードキャストモードと呼ばれる別の動作モードについて説明しています。ブロードキャストモードでは、接続は行われず、アプリケーションデータは広告パケットの一部として送信されます。多くのAndroid/iOS電話は各パケットを同時にスキャンできるため、これは私のニーズにぴったりです。広告パケットはバーストで複数回送信されるため、データの受信はほとんど信頼できると思われます。パケットがあちこちで失われた場合、それは許容されます。
これが興味深いのは、これらのパケットに10〜20Hzのレートで更新されるライブセンサーデータを伝送することです。私がウェブで見つけた例から、このモードのBLEは、主に静的データをブロードキャストする「iBeacon」タイプの実装に使用されています。 Androidスタック内で広告パケットがどのようにフィルタリングされるかについての情報を見つけることができません。Bluetoothハードウェアアドレスごとに1つの結果を返すか、アドレスとデータの一意の組み合わせである可能性があります。このアプリケーションでは2番目のオプションが機能しますが、スキャンを開始および停止するとフィルターがリセットされる場合は、何かを機能させることもできます。
Androidのドキュメントでは、スキャンメソッドでのデバイスフィルタリングの仕組みについては何も言及していません。この同じ問題を解決しようとするネット上の1つの投稿を見つけることができました。 BLE:スキャン中の同じ周辺機器の複数の発見 。iOSでは、これを可能にするスキャン機能に渡すことができるパラメーターがあることを同僚から教えられました。
AndroidソースのstartLeScan()呼び出しからコードをトレースバックしようとしましたが、コードは非常に複雑であり、抽象化の使用により実装の識別が困難になりました。取得した最も遠いのは、BluetoothManagerServiceクラスのメソッドgetBluetoothGatt()から返されたIBluetoothGattオブジェクトです。このオブジェクトは、スキャンを開始する要求を受け取ります 現在のリビジョンのBluetoothManagerService.Java の790行目はgithubにあります。オブジェクトはメッセージの結果からキャストされているため、結果は電話/ドライバー固有のものであると思われます。さらにトレースすることができます。
私が解決したい別の質問は、スキャンのオンとオフをどれだけ速く切り替えることができるかです。スキャンは電力を集中的に使用する操作ですが、データのブロードキャストはかなり正確なリアルタイムタイマーで定期的に行われます。結果として、ブロードキャストとスキャンが同期され、スキャナーが他の90%以上の時間をシャットダウンするように、スキャンのオンとオフを切り替えることができれば、最適な最適化になります。これはおそらく実験的にテストする必要があります。
Android用アクセサリでこれが可能かどうかを確認するために、私はまだ実行可能性調査を行っています。私の現在の電話はまだバージョン4.3を実行できないので、これを実験的にテスト/ハッキングする方法はありません。
Android 4.3および4.4の場合、これは混乱のようです。一部のデバイスは、 onLeScan(BluetoothDevice device、int rssi、byte [] scanRecord) iOSのようにフィルタリングを設定する方法はありません(Arkadiusz Koniorの回答を参照してください)。ユーザーにそのような質問をすることができないため、リストを開始します。彼らのデバイス。
ただし、スキャンを再開しても、「フィルタリングしない」デバイスでは問題ありません。そのため、すべてのデバイスでスキャンを再開します。
フィルタリングしない(onLeScan()を連続的に呼び出す)
デバイスのフィルタリング(標準に適用)
不明なフィルタリング動作(デバイスを特定のグループに関連付けるのを助けてください)
Bluetooth仕様(Core_v4.1.pdf)の広告レポートの重複に関する2535-2536ページのテキストは、いくぶん不明瞭です。ただし、1258ページのテキストは明確です。 HCI_LE_Set_Scan_EnableコマンドにFilter_Duplicatesパラメーターを指定します。 Androidバージョン4.4(KitKat)では、このパラメーターは0x00(重複フィルタリングが無効)です。
BluetoothチップでAndroidバージョン4.4(KitKat)からフィルタリングが行われたかどうかを確認する簡単な方法があります。電話を開発者の電話にし、開発者オプションを入力し、[Bluetooth HCIを有効にする次に、Bluetoothを一度オフにしてからオンにして、設定を噛みます。これ以降、アプリケーションプロセッサとBluetoothチップ間のすべてのHCIパケットは、adb pull storage/emulated/legacy/btsnoop_hci.log。これはテキストファイルではないため、 http://www.fte.com/products/default.aspx またはbtsnoop_hci.logを表示するにはwiresharkのプログラムが必要です。古いバージョンはBLEをサポートしていないため、かなり新しいバージョンが必要です私の経験では、Bluetoothチップにはフィルタリングが一切行われていない、つまり、BluetoothチップのADV_INDおよびADV_NONCONN_INDごとにHCIイベント「LE Advertising Report Event」が送信されますこれは、Bluetoothチップを搭載した携帯電話に適用されますQualcomm/Atheros WCN 3680およびBロードコムBCM 4339。
修正:btsnoop_hci.logへのパスは、電話メーカーによって異なる場合があります。 adb Shell cat etc/bluetooth/bt_stack.confで正しいパスを見つけることができます| grep BtSnoopFileName
BLEを使用してAndroid 4.3(Nexus 4&7)のアプリケーションを開発しています。観測から、スキャン要求がペリフェラルに返されなかった場合、スキャンは同じデバイスを複数回返します。
デバイスは、パッシブとアクティブの2つの方法でアドバタイズできます。パッシブモードでは、周辺機器はすべてのデータをアドバタイズするだけであり、定期的なパケットの送信後にリッスンしません。送信中、スリープ中、送信中、スリープ中...アクティブモードではセンサーもアドバタイズしますが、メッセージは可能な限り短くなっています。それを送信した後、非常に短い時間のリスニングに切り替わります。スキャンがショートメッセージを検出すると、すぐにSCAN REQUESTコマンドをペリフェラルに送信し、より詳細な応答を取得します。私が見る限り、Androidは1回のスキャン中にSCAN REQUESTを複数回送信しません。
範囲内に2つのデバイスがあると仮定しましょう。 1つはf.eです。 NordicのnRF Tempセンサー(パッシブ広告)と他の1つの接続可能なデバイス。次のスキャン応答を受け取りました。
11-10 21:32:54.281: D/BluetoothAdapter(13468): startLeScan(): null
11-10 21:32:54.281: D/BluetoothAdapter(13468): onClientRegistered() - status=0 clientIf=4
11-10 21:32:54.321: D/BluetoothAdapter(13468): onScanResult() - Device=CD:61:1A:A8:BC:BE RSSI=-94
11-10 21:32:55.122: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61
11-10 21:32:56.414: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62
11-10 21:32:57.715: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61
11-10 21:32:59.016: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:01.609: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:02.901: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:04.212: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62
11-10 21:33:04.282: D/BluetoothAdapter(13468): stopLeScan()
ご覧のとおり、接続可能なデバイスは一度だけ表示され、もう一方は7回表示されます。
私が解決したい別の質問は、スキャンのオンとオフをどれだけ速く切り替えることができるかです。スキャンは電力を集中的に使用する操作ですが、データのブロードキャストはかなり正確なリアルタイムタイマーで定期的に行われます。結果として、ブロードキャストとスキャンが同期され、スキャナーが他の90%以上の時間をシャットダウンするように、スキャンのオンとオフを切り替えることができれば、最適な最適化になります。これはおそらく実験的にテストする必要があります。
スキャン頻度はデバイスによって異なります。さらに、広告は通常、3つのチャネル(37、38、および39)で行われ、発見される可能性を高めます。ただし、「アクティブな」デバイスから広告パケットを複数回取得することは非常に良い考えです。
実際のBluetooth仕様には次のように書かれています:
ホストに重複した広告レポートを送信する必要はありません。重複した広告レポートは、リンク層がスキャン状態にある間、同じデバイスアドレスの広告レポートです。広告データは変更される場合があります。 広告データまたはスキャン応答データは、重複する広告レポートを決定する際に重要とはみなされません。
仕様によると、これはスキャン期間内に適用されます。これは、広告を受信するたびにスキャンを停止して再開することを推奨します。
BLEでの私の経験に基づいて、広告で変数データを送信することはあまり良い考えではないようです。ほとんどすべてのことは、広告からのデータが変化しないことを前提としています。実際に可変データ(温度計の読み取り値など)を送信する場合は、実際にデバイスに接続し、特性を介して送信することをお勧めします。それはより信頼性が高く、はるかに少ない電力を使用します。欠点は、一度に8つのデバイスにしか接続できないことです。
広告は、デバイスの存在を検出して識別するためのものです。
IOSでは、このフラグの名前はCBCentralManagerScanOptionAllowDuplicatesKey
です。スキャン機能に渡すと、すべての通知パケットの通知が発生します。 Androidで同様のフラグが見つかりませんでした。