Bluefruit LE Snifferを使って、Android端末とCC2541 SensorTag間のBLEプロトコルデータをキャプチャして、そのデータをWiresharkを使って解析します。「Bluefruit LE Snifferを使用したBLEプロトコル解析」でBluefruit LE Snifferを使って、二つのBLEデバイス間のデータをキャプチャーしました。「Android携帯を使ってCC2541 SensorTagから温度データの取得」でAndroid携帯を使ってCC2541 SensorTagから温度データを取得しました。

動作環境

  • Windows10 Pro
  • nRF51822搭載 Bluefruit LE Sniffer
  • Wireshark Version 3.0.5
  • Python 3.8.0
  • CC2541 SensorTag アドレス「99_4c_64_cd_df」
  • Android携帯:京セラ android one s2 アドレス「5e:d8:fe:3c:af:91」
  • Androidバージョン:7.1.2
  • Android開発環境:Android Studio Bumblebee | 2021.1.1

Bluefruit LE Snifferによるキャプチャ

Bluefruit LE Snifferによるキャプチャが、「Bluefruit LE Snifferを使用したBLEプロトコル解析」に従ってもうまくできないときは、ツールバーの「Device」に通信を見たいペリフェラルデバイス、今回の場合は次のように「SensorTag」を選択します。

しばらくして、上の画像のようにSourceのカラムがMaster_xxxxやSlave_xxxxに変われば、もしくは「Protocol」が「ATT」となれば、SensorTagがキャプチャされています。

また、セントラルデバイスとペリフェラルデバイスの接続のときに、よくSnifferが落ちます(WireSharkのログが止まりLEDが点滅しなくなります)。公式ドキュメントのFAQに次のように記述されています。

これは、Nordic社のスニファーのファームウェアの制限です。 Bluetooth Low Energyのアドバタイジングは、3つの専用チャンネルで行われ、それぞれが独自の周波数で動作します。 スニッファーが接続を追跡するためには、接続が起こったときに正しいチャンネルを見ている必要があり、2/3の確率で別のチャンネルを見ている可能性があります。
接続を捕捉し、接続後のデータ交換を確認するためには、スニファーとペリフェラルデバイスとセントラルデバイスの間でチャンネルが揃うまで、何度か接続する必要があります。

アドバタイジングシーケンス

SensorTagとAndroid端末とのアドバタイジングシーケンスを次に示します。

  1. SensorTagは定期的に「ADV_IND」パケットでアドバタイズを送信してAndroid端末との接続を待ちます。
  2. Android端末は定期的にスキャンし、アドバタイズを受信します。情報が不足している場合、Android端末は 「SCAN_REQ」パケットを送信します。
  3. SensorTagが 「SCAN_REQ」 パケットを受け取ると、その応答として「SCAN_RSP 」パケットを送信します。
  4. アドバタイジング・パケットの送受信が完了し、Android端末からSensorTagに対して接続要求が行われると、 「CONNECT_REQ 」パケットが送信され、接続状態に切り替わります。
  5. Android端末とSensorTagはそれぞれマスター(Master)とスレイブ(Slave)になり、 Wireshark での Source と Definition のデバイス表示も、 MAC アドレス表示から Master, Slave に切り替わります。

Wireshark で取得したデータを解析します。

  • 「ADV_IND」パケットは複数回送信されます。また、「SCAN_REQ」 パケットと「SCAN_RSP 」パケットのやり取りは複数回行われます。「CONNECT_REQ 」パケットの送信は1回だけ行われ、以降マスター(Master)とスレイブ(Slave)の関係になります。
  • 次のように「SCAN_RSP 」パケットでデバイス名「SensorTag」を通知しています。
  • 「CONNECT_REQ 」でなく「CONNECT_IND」と表示されています。次のようにパケットが「PDU Type: 0x5 」となっているので、標記の誤りと考えられます。

温度データ取得シーケンス

SensorTagとAndroid端末を使ってSensorTagから温度データを取得するシーケンスは次のようになっています。

  1. Android端末は、「Write Request」パケットで温度データの取得要求をSensorTagに送信し、SensorTagから「Write Response」パケットを受信します。
  2. Android端末は、CCCD (Client Characteristic Configuration Descriptor)への書き込みを行う「Write Request」パケットをSensorTagに送信し、SensorTagから「Write Response」パケットを受信します。この設定によりNotifyでAndroid端末に温度データが通知(コールバック)されます。
  3. Android端末は、「Handle Value Notification」パケットによりSensorTagから温度データを受信します。

温度データを取得するためのCC2541 SensorTagのUUIDは、プログラムにより次のように定義されています。

    private final String TEMP_SERVICE = "f000aa00-0451-4000-b000-000000000000";
    private final String TEMP_DATA = "f000aa01-0451-4000-b000-000000000000";
    private final String TEMP_REQ = "f000aa02-0451-4000-b000-000000000000";
    private final String NOTIFY_DESCRIPTOR = "00002902-0000-1000-8000-00805f9b34fb";

Wireshark で取得したデータを解析します。

  • 温度データの取得を要求する「Write Request」パケットを次に示します。
  • CCCD (Client Characteristic Configuration Descriptor)への書き込みを行う「Write Request」パケットを次に示します。
  • 「Handle Value Notification」パケットによるSensorTagからの温度データを次に示します。