【 無線化講座が「本」になりました 】ムセンコネクト著書『Bluetooth無線化講座』出版決定

Bluetooth APIを用いたWindowsアプリでのBLEアドバタイズパケットの受信方法【第5回】

こんにちは。ムセンコネクト三浦です。

前回の記事で「センサ搭載BLEビーコン」が完成しました。最終回となる今回は「WindowsパソコンでBLEスキャンを行い、ビーコンが発信したセンサ値(アドバタイズパケット)を取得する方法」について解説します。

目次

WindowsでBLEスキャンを実行するには?

本記事の対象は、一度Pythonを実行したことがあるエンジニアを想定しています。

Windowsで簡単にBLEスキャンを行うには、Pythonとbleakを使うのがおすすめです。

bleakのインストールコマンド

pip install bleak

サンプルコード

async def start_scan():
    ble_scanner = BleakScanner(on_advertisement_received)

    await ble_scanner.start()
    while True:
        await asyncio.sleep(1.0)

asyncio.run(start_scan())

asyncio(awaitのようなPythonの特殊な文法)がここだけ必要になります。アドバタイズの受信だけに限ればあまり重要な箇所ではないので、一旦ここでは割愛します。

以下のコードに注目してください。

ble_scanner = BleakScanner(detection_callback=on_advertisement_received)

BleakScanner生成時に引数detection_callback として関数を与えてあげると、スキャン開始後にアドバタイズを受信したタイミングでその関数が呼び出されるようになります。

このコールバック関数では、BLEDeviceAdvertisementDataの2つを受け取ることができるので、そこでアドバタイズデータの解析が行えます。

def on_advertisement_received(device: BLEDevice, advertisement_data: AdvertisementData):
    ...

アドバタイズデータを解析してみる

通信仕様書を見ながらbytesをスライス・整数変換して、データを解析していきます。

AdvertisementDataからService Dataのバイト列を取得します。

OPEN_SENSOR_SERVICE_UUID = normalize_uuid_str("FCBE")

...

    service_data = advertisement_data.service_data.get(OPEN_SENSOR_SERVICE_UUID)

advertisement_data.service_dataはdict(辞書オブジェクト) です。 キーが Service UUID文字列、値がServiceDataバイト列です。

ただし、このキーは128bit UUID文字列なので、16bit表現から変換する必要があります。bleakが提供するnormalize_uuid_str()を使えば、短縮された16bit UUID文字列から128bit UUID文字列が得られます。

今回のデータの確認

今回はデータ種別が照度のデータ構造のものを例に解析してみます。 照度データのアドバタイズフォーマットは以下のようになっています。

OffsetSizeFieldDescription備考
010x0BLength
110x16Service Device data type value
220xFCBEOpen Sensor Serviceオープンセンササービスでは固定値0xFCBEを利用します
410x01Data Schema Version現状は固定値0x01を利用します
540xXXXXXXXX個体識別番号4バイト固定
910x13データ種別=照度(2byte)
1020xXXXX照度データ2バイト unsigned 単位:0.1lx

Pythonでバイト列を整数に変換する

解析にはint.from_bytesを使い、フィールドに対応するバイト列を抜き出し、int型に変換していきます。

この関数を使ってデータ種別、照度データなどを取り出します。

    data_schema_version = int.from_bytes(
        service_data[0:1],
        byteorder="big",
        signed=False,
    )

    device_identifier = int.from_bytes(
        service_data[1:5],
        byteorder="big",
        signed=False,
    )

    data_type = int.from_bytes(
        service_data[5:6],
        byteorder="big",
        signed=False,
    )

    illuminance = int.from_bytes(
        service_data[6:8],
        byteorder="big",
        signed=False,
    )
    illuminance_lx = illuminance * 0.1  # NOTE: 単位=0.1lxのため変換

Data Schema Versionの解析部分を例に説明します。

    data_schema_version = int.from_bytes(
        service_data[0:1],
        byteorder="big",
        signed=False,
    )

int.from_bytesには変換したいバイト列、バイトオーダー、符号の有無を表す bool値の3つを渡します。

アドバタイズフォーマットを見るとData Schema Versionのsizeは1、service dataは Data Schema Versionから始まっているので、service_data[0:1]として対応する部分のバイト列をスライスしています。

バイトオーダーや符号については通信仕様書を確認して、都度適切なものを指定してください。

このようにしてパースしたデータ種別やデータ値をprintで標準出力させれば、Windowsパソコン上でセンサ値の確認ができるようになります。

別のBLEデバイスからのアドバタイズと区別する

on_advertisement_receivedは、別のBLEデバイスからのアドバタイズ受信時でも呼ばれるため、コールバック内で受信対象のデバイスからのアドバタイズデータかどうか判断する必要があります。

Open Sensor ServiceのServiceDataが得られなければ排除

AdvertisementDataからService Dataのバイト列を取得するときにUUIDを指定してservice dataを取得していましたが、UUIDが一致しない場合はNoneが返るので、対象のデバイスではないとみなします。

    if service_data is None:
        return

今回のデモ用ServiceDataの長さ (8) とマッチしてなければ排除

今回のデバイスが発するservice dataバイト列のlengthは (8) なので、一致するかどうか判断します。

    if len(service_data) != 8:
        return

ただし、lengthチェックだけでは照度のデータ構造であると確定することはできないので、バイト列の解析を行ってData Schema Versionとデータ種別を取り出し、それぞれの値を確認します。

現行のデータスキームバージョン (1) とマッチしてなければ排除

Data Schema Version情報はバージョンの確認に使用します。バージョンによってフォーマットが変更されている可能性があるので、対象デバイスと同じバージョンか確認する必要があります。

    if data_schema_version != 0x01:
        return

データ種別が「照度」 (0x13) とマッチしてなければ排除

データ種別が照度かどうかも確認します。

    if data_type != 0x13:
        return

完成したデモ動画

今回はPythonで簡単にBLEスキャンし、解析する方法を紹介しました。

照度データのアドバタイズフォーマットの解析を行うソースコードは下記リンクからダウンロード可能です。

これで「センサデータを発信するBLEビーコン」と「センサデータを受信するWindowsアプリ」が完成しました。

完成したデモはこちらです。

まとめ

ムセンコネクトでは、誰でも自由に、手軽にBLEビーコン通信を試せるビーコンフォーマット「オープンセンササービス」を通じて、BLEビーコンの普及に取り組んでまいります。

本企画、BLEビーコン、または「オープンセンササービス」についてのご意見、ご感想、ご不明な点などございましたら、ぜひムセンコネクトまでご連絡ください。みなさまからの忌憚のないご意見をお待ちしております。

よろしければシェアをお願いします
目次