Bluetooth® Low Energyを受信する

とある案件の基礎段階で、Bluetoothの受信を研究しています。

Bluetooth® Low Energy(BLE)機器の多くは、自分の存在や情報を周囲へ知らせるため、「Advertisement(アドバタイズメント)」と呼ばれる告知データを定期的に送信しています。
Python+WinRTを使って、受信したAdvertisementを取り出し、BLEアドレス、RSSI、Local Name、AD Type、RAWデータを取りだしてみました。

サンプルコード

まずはパッケージの導入

pip install winrt-Windows.Devices.Bluetooth.Advertisement
pip install winrt-Windows.Storage.Streams

上は、Windowsが持っているBLEのAdvertisement送受信機能
下は、Windows Runtimeで扱われるバイナリデータ(バッファやストリーム)を読み書きするため
です
(※この解説中、ライセンス表記などは省略しています)

Python
from winrt.windows.devices.bluetooth.advertisement import (
    BluetoothLEAdvertisementWatcher,
    BluetoothLEScanningMode,
)
from winrt.windows.storage.streams import DataReader


def read_buffer(buffer):
    reader = DataReader.from_buffer(buffer)
    data = bytearray(reader.unconsumed_buffer_length)
    reader.read_bytes(data)
    reader.close()
    return bytes(data)


def format_address(address):
    text = f"{address:012X}"
    return ":".join(text[i:i + 2] for i in range(0, 12, 2))


def on_received(sender, args):
    ad = args.advertisement
    data_list = []

    for i in range(len(ad.data_sections)):
        section = ad.data_sections[i]
        raw = read_buffer(section.data)

        data_list.append(
            f"0x{section.data_type:02X}:{raw.hex(' ').upper()}"
        )

    print(
        f"{format_address(args.bluetooth_address)}  "
        f"RSSI={args.raw_signal_strength_in_d_bm:4d} dBm  "
        f"NAME={ad.local_name or '-'}  "
        f"AD={' | '.join(data_list) or '-'}"
    )


watcher = BluetoothLEAdvertisementWatcher()
watcher.scanning_mode = BluetoothLEScanningMode.ACTIVE
watcher.add_received(on_received)

watcher.start()

print("BLE Advertisementを受信中です。Enterで終了します。")

try:
    input()
except KeyboardInterrupt:
    pass

watcher.stop()

WatcherとReceivedイベント

  • BluetoothLEAdvertisementWatcherがWindowsのBLE Advertisement受信機能への入口です。
  • Active scanでは、対応機器からScan Responseも受信できる場合があります。
  • add_receivedで、Advertisementを受信するたびに呼ばれる関数(on_received)を登録します。
  • 終了時にはWatcherを停止します。

BLEアドレスとRSSI

  • Windowsから渡されるアドレスは整数なので、`format_address`で`AA:BB:CC:DD:EE:FF`形式にします。BLEではプライバシー保護のためアドレスが変化する機器もあり、アドレスだけで同じ物理機器だと断定はできません。
  • RSSIは受信信号強度ですが、距離の厳密な測定値ではありません。機器の向き、遮蔽物、反射、送信出力でも変化します。

IBufferとRAWデータ

  • Advertisementの各データ部分はWinRTのIBufferとして渡されます。read_bufferDataReaderでPythonのbytesへコピーし、最後にReaderを閉じます。
  • data_sectionsはWinRTのコレクションです。このサンプルは要素番号で取り出します。
  • 各セクションはAD Type:RAWデータとして表示します。AD Typeに標準的な意味があっても、データ内部がメーカー独自または個別規格である場合があります。

取得できるのは、Windows APIがアプリへ渡したBLE Advertisement情報です。Bluetooth Classic、接続後のGATT通信全体、暗号化された接続データ、無線リンク層の全チャネル、他機器同士の通信は表示できません。

実行結果

BLE Advertisementを受信中です。Enterで終了します。
AA:BB:CC:DD:EE:01  RSSI= -66 dBm  NAME=-            AD=0x01:06 | 0xFF:E0 07 XX XX XX XX | 0x03:03 40
AA:BB:CC:DD:EE:01  RSSI= -67 dBm  NAME=EDIFIER BLE  AD=0x09:45 44 49 46 49 45 52 20 42 4C 45
AA:BB:CC:DD:EE:02  RSSI= -58 dBm  NAME=-            AD=0xFF:06 00 XX XX XX XX XX XX

こんな感じで出力されます。
この表示から、周囲に少なくとも2台のBLE機器があり、電波を受信できていることがわかります。
AA:BB:CC:DD:EE:01などは機器を識別するためのBluetoothアドレス、RSSIは受信した電波の強さで、一般に0に近いほど強いことを示します。上の2行は同じBluetoothアドレスから受信したデータです。
NAMEから「EDIFIER BLE」という機器名も確認できます。
ADには、機器が周囲へ発信している各種情報が16進数で表示されています。

セキュリティとプライバシー

受信専用でも、BLEアドレス、Local Name、Manufacturer Dataなどは機器や場所の識別につながることがあります。

  • 自分が管理する場所、または許可を得た環境で使用してください
  • 人の追跡、認証回避、秘密情報の収集に使用しないでください
  • 実在するアドレスやRAW値をWebへ載せる際は匿名化してください
  • 法令、施設規則、機器の利用条件に従ってください

免責事項

本記事および掲載コードは、BLE Advertisementの受信方法を技術的に解説することを目的としたものです。動作や正確性、安全性を保証するものではありません。利用にあたっては、関連する法令、施設の規則、機器の利用条件等をご確認のうえ、ご自身の責任でご利用ください。本記事および掲載コードの利用によって生じた損害について、当社は責任を負いかねます。

ライセンスと商標

掲載コードとダウンロードサンプルはMIT Licenseです。PyWinRTもMIT Licenseですが、本サンプルとは別のプロジェクトです。公開・再配布時には各ライセンスを確認してください。
Bluetooth®のワードマークおよびロゴはBluetooth SIG, Inc.が所有する登録商標です。本記事およびサンプルはBluetooth SIG, Inc.の承認、提携または認定を示すものではありません。

応用アプリ:BLEInspector

ここまで紹介したBLE Advertisementの受信処理を応用して、周辺のBLE機器をGUIで確認できるWindowsアプリ「BLEInspector」を作成しました。
BLEアドレス、RSSI、Local Name、AD Type、Manufacturer Data、Service Data、UUID、RAWデータなどを画面上で確認できます。
Pythonの実行環境を用意せずに使用できるWindowsアプリとして公開します。
動作環境:Windows 11
BLEInspectorをダウンロード(zip形式)] (http://sketlab.jp/download/BLEInspector/BLEInspector_0.3.0_Windows_x64.zip
 ファイル名:BLEInspector_0.3.0_Windows_x64.zip

SHA-256ハッシュ値:
 AB7C69B30FD3B7B9FD57AEB697D332783EF8817F1E7CAC3546C39B18E7479D92
[ハッシュ値チェッカーを開く]
https://sketlab.jp/script/Javascript/sha256-check.html
ハッシュ値チェッカーでダウンロードしたZIPを選択し、上記のSHA-256ハッシュ値を入力すると、ファイルが配布時のものと一致するか確認できます。

ダウンロード後はZIPを展開し、フォルダー内の`BLEInspector.exe`を起動してください。
使い方詳細は同梱しているマニュアルを良くお読みください。

※本アプリはBLE Advertisementの観察・解析を目的としたツールです。使用にあたっては、本ページ記載の「セキュリティとプライバシー」および「免責事項」をご確認ください。

参考資料

Microsoft Learn:BluetoothLEAdvertisementWatcher.Received  
Microsoft Learn:Bluetooth LE advertisements  
PyWinRT公式リポジトリ  
Bluetooth SIG:Brand and trademarks  

← 技術記事一覧へ戻る