bleakを用いたbluetooth検出(2024/7/15記述)

:::note warn
警告
この記事は自分自身の理解を深めるため、アウトプットを兼ねた記事になります。そのため、間違った理解があるかもしれませんが、承知の上、読んで頂けると助かります
:::
 この記事ではPythonのライブラリであるbleakを用いてアドバタイズ通信しているbluetoothデバイスを検出します。使用環境は以下に記載します
<dl>
    <dt>使用環境</dt>
    <dd>OS : Sonoma(macOS) 14.4.1</dd>
    <dd>Python 3.10.12</dd>
    <dd>bleak 0.21.1</dd>
</dl>

# bleakでのデバイス検出
　[bleak]("https://github.com/hbldh/bleak")はbluetoothに関連するライブラリです。私も全容は把握しきれていませんが、現在でも更新されているライブラリであり、isuuesにも数多くの問題点が投稿されているため、エラー対処もしやすいです。

　実際に自分がスキャンしたプログラムを以下に記載します。
 ```ruby:scan.py
import asyncio
from bleak import BleakScanner
import json

async def main():
    scanner = BleakScanner()

    await scanner.start()
    await asyncio.sleep(5.0)
    await scanner.stop()

    # 確認できたdeviceの情報を取得する
    devices = scanner.discovered_devices_and_advertisement_data

    #jsonファイルへの書き出し
    with open('sample.json','w') as f:
        json.dump(devices, f, default=str, indent=2)

 ```
 プログラム通りですが、始めにアドバタイズ通信をしているbluetoothを受信するため、5秒間のスキャンを行っています。その後、スキャンしたデバイスをjsonファイルへ書き出しています。
 書き出したjsonファイルは以下になります。
 ```ruby:bluetooth_device.json
 {
  "82B4EA49-1F3D-A48B-5BCB-5A2D3C46648A": [
    "82B4EA49-1F3D-A48B-5BCB-5A2D3C46648A: None",
    [
      null,
      {
        "76": "b'\\x16\\x08\\x00U\\xb2\\xfa\\xd59\\t\\xed'"
      },
      {},
      [],
      null,
      -59,
      [
        "<CBPeripheral: 0x1228e5bf0, identifier = 82B4EA49-1F3D-A48B-5BCB-5A2D3C46648A, name = (null), mtu = 0, state = disconnected>",
        "{\n    kCBAdvDataIsConnectable = 0;\n    kCBAdvDataManufacturerData = {length = 12, bytes = 0x4c0016080055b2fad53909ed};\n    kCBAdvDataRxPrimaryPHY = 129;\n    kCBAdvDataRxSecondaryPHY = 0;\n    kCBAdvDataTimestamp = \"742719657.145946\";\n}",
        -59
      ]
    ]
  ],
  "2E9AD652-7264-F7D8-2E44-1F893ADEB0C8": [
    "2E9AD652-7264-F7D8-2E44-1F893ADEB0C8: YamahaAV",
    [
      "YamahaAV",
      {},
      {},
      [
        "945ca2b0-852c-4ab8-b654-354df41c2795"
      ],
      null,
      -94,
      [
        "<CBPeripheral: 0x110809a10, identifier = 2E9AD652-7264-F7D8-2E44-1F893ADEB0C8, name = YamahaAV, mtu = 0, state = disconnected>",
        "{\n    kCBAdvDataIsConnectable = 1;\n    kCBAdvDataLocalName = YamahaAV;\n    kCBAdvDataRxPrimaryPHY = 129;\n    kCBAdvDataRxSecondaryPHY = 0;\n    kCBAdvDataServiceUUIDs =     (\n        \"945CA2B0-852C-4AB8-B654-354DF41C2795\"\n    );\n    kCBAdvDataTimestamp = \"742719661.0294631\";\n}",
        -94
      ]
    ]
  ]
}
 ```
 今回のスキャンでは2つのbluetoothデバイスをスキャンしていることが確認できます。これらを読み解くには[bleak公式ドキュメント]("https://bleak.readthedocs.io/en/latest/api/scanner.html#bleak.BleakScanner.discovered_devices_and_advertisement_data")に記載されている`scanner.discovered_devices_and_advertisement_data`で取得できる情報を理解する必要があります(今回はこの情報をjsonファイルに記述したため)。

## 取得したbluetoothデバイスから分かること
　公式ドキュメントを読めば何が検出できるのかは分かりますが、1つ例を示します。今回は2つのbluetoothデバイスが取得できましたが、始めに取得できたデバイスに注目します。
 ```
 "82B4EA49-1F3D-A48B-5BCB-5A2D3C46648A": [
   "82B4EA49-1F3D-A48B-5BCB-5A2D3C46648A: None",
   [
     null,
     {
       "76": "b'\\x16\\x08\\x00U\\xb2\\xfa\\xd59\\t\\xed'"
     },
     {},
     [],
     null,
     -59,
     [
       "<CBPeripheral: 0x1228e5bf0, identifier = 82B4EA49-1F3D-A48B-5BCB-5A2D3C46648A, name = (null), mtu = 0, state = disconnected>",
       "{\n    kCBAdvDataIsConnectable = 0;\n    kCBAdvDataManufacturerData = {length = 12, bytes = 0x4c0016080055b2fad53909ed};\n    kCBAdvDataRxPrimaryPHY = 129;\n    kCBAdvDataRxSecondaryPHY = 0;\n    kCBAdvDataTimestamp = \"742719657.145946\";\n}",
       -59
     ]
   ]
 ],
 ```
 　上記に` "76": "b'\\x16\\x08\\x00U\\xb2\\xfa\\xd59\\t\\xed'"`と記載があります。公式ドキュメントによるとこの情報はmanufacture_dataらしく、製品情報が含まれています。int型とbytes型がありますが、**int型はbluetoothデバイスがどこの製品か**、**bytes型はデバイスの詳細な情報**を含んでいます。
  
 　int型はbluetooh公式HPに載っている[Assinged Numbers Document(PDF)]("https://www.bluetooth.com/specifications/assigned-numbers/")に記載されている企業名を調べることで、どの企業の製品か分かります。bleakはint型で出力しますが、PDFに載っている企業は16進数で記載されているため、この点だけは注意が必要です。今回のintは76を取得できているため、Documentで調べると**Apple.inc**であることが判明しました。従って、このbluetoothデバイスはApple製品であることが分かりました。

　補足として2つ目のbluetoothデバイスのmanufacture_dataに注目するとint型とbytes型に別れていないことが分かります。これはbluetooth公式HPに記載されている企業ではないため、企業独自で決定しているのではないかと考えています。
  
 　bytes型を読み解くことは難しく、デバイスの仕様書が無ければ全てを理解することはできません。これはユーザのプライバシ問題にも関わるため、基本的には仕様書は公開されていないようです。(ビーコンなど一部のデバイスはオンライン上に仕様書が公開されている)