11.2. BLE スタック

ネットワーキングと同様に、Bluetooth Low Energy は層のスタックとして構築されており、各層が単一の問題を解決し、その上の層にきれいな抽象化を提供します。以下の名前は Bluetooth Core 仕様からそのまま取ったもので、aioble および bluetooth の API に登場します。

5 つのラベル付きボックスの垂直スタック。下から上へ: Physical(無線)、Link Layer、GAP、GATT、Application。右側の矢印はスタックを上向きに指し「私たちが構築するもの」とラベル付けされています。左側の矢印はスタックを下向きに指し「提供されるもの」とラベル付けされています。

Bluetooth Low Energy スタック。各層は、ネットワーキングスタックが使うのと同じパターンで、よりきれいな抽象化を次の層へと渡します。

物理層。 2.4 GHz の無線を介して 2 つのデバイス間で ビット を移動します。チャネル選択、変調、送信電力。カメラの仕事は電源が入っていることであり、残りはシリコンが行います。

リンク層。 互いに通信することに合意した 2 つのデバイス間で パケット を移動します。各パケットを 1 つの隣接デバイスに向けられるようにデバイスアドレスを追加し、接続を構成する周期的な無線イベントをスケジュールし、受信側が確認応答しなかったパケットの再送を処理します。

Generic Access Profile (GAP)。 発見と接続の層です。4 つの ロール(ブロードキャスター、オブザーバー、ペリフェラル、セントラル)と、そもそも 2 つのデバイスが互いを見つけられるようにする アドバタイジングスキャニング プロトコル、さらにそれらの間で接続を開いたり閉じたりする手順を定義します。アドレス、アドバタイジングペイロード、接続パラメータ、ペアリングが存在するのはここです。

Generic Attribute Profile (GATT)。 データ層です。開いた GAP 接続の上に位置し、小さなキー/値データベースを公開します。一方の側が キャラクタリスティック と呼ばれる名前付き値のツリーをホストし、もう一方の側がそれらを読み取り、書き込み、またはサブスクライブします。実際のアプリケーションのバイトが流れるのはここです。

アプリケーション。 カメラとピアがバイトの意味として合意した内容です。Bluetooth SIG は、よく使われるキャラクタリスティックを定義する標準 プロファイル(心拍数、バッテリーレベル、環境センシング)を公開しており、無関係なデバイスどうしが相互運用できるようにしていますが、どのアプリケーションも自由に独自のものを定義できます。

11.2.1. 層が実行時にどう積み重なるか

このパターンはネットワーキングスタックと一致します:

  • アプリケーションのバイトは キャラクタリスティック値 に入ります。

  • GATT は、そのバイトがどのキャラクタリスティックに属するかを識別するヘッダーでそれをラップします。

  • GAP は開いた接続を維持し続けるので、GATT には送る先があります。

  • リンク層は、それらをまとめてピアのデバイスアドレス宛のパケットにラップし、それを送信する無線イベントをスケジュールします。

  • 物理層は、パケットを 2.4 GHz 無線の短いバーストに変換します。

物理層とリンク層は、Python からはほとんど見えません。シリコンと無線ファームウェアがそれらを処理します。GAP より上では、カメラの Python コードがより多くを担うようになります。

11.2.2. ユーザー向け API がひそかに省略する 2 つの層

Bluetooth 仕様は、リンク層と GAP/GATT の間に位置するさらに 2 つの層を挙げています。Host Controller Interface(HCI)はホスト CPU が別個の無線チップを駆動するために使うプロトコルであり、L2CAP は 1 つのリンク層接続を複数の論理チャネルに分割するマルチプレクサです。

どちらも aioble API では見えませんが、どちらも消えてなくなるわけではありません。HCI は BLE ポートの内部に位置し、カスタムビルドの MicroPython を使っていない限り見えません。L2CAP は GATT がその上で動作するキャリアです。生のバイトストリームを必要とするアプリケーションは、独自の L2CAP チャネルを要求できます(L2CAP チャネル)。