bluetooth --- 低レベルBluetooth

このモジュールは、オンボードのBluetoothコントローラへのインターフェイスを提供します。Bluetooth Low Energy (BLE) のCentral、Peripheral、Broadcaster、Observerの各ロール、さらにGATTサーバーおよびクライアント、L2CAPのコネクション指向チャネルをサポートします。1つのデバイスが複数のロールで同時に動作することもできます。ペアリングおよびボンディングもサポートされています。

このAPIは低レベルのBluetoothプロトコルに対応することを意図しており、特定のデバイスタイプなど、より高レベルの抽象化のための構成要素を提供します。

Tip

ほとんどのアプリケーションでは、このモジュールをasyncioベースでラップした、より高レベルの aioble ライブラリの利用をおすすめします。aioble --- 非同期 BLE を参照してください。

class BLE

class bluetooth.BLE

シングルトンのBLEオブジェクトを返します。

設定

active(active: bool | None = None, /) bool

オプションでBLE無線のアクティブ状態を変更し、現在の状態を返します。

このクラスの他のメソッドを使用する前に、無線をアクティブにしておく必要があります。

config(param: str, /) Any
config(*, **kwargs: Any) None

BLEインターフェイスの設定値を取得または設定します。値を取得するには、パラメータ名を文字列として引用符で囲み、一度に1つのパラメータのみを問い合わせます。値を設定するにはキーワード構文を使用し、一度に1つ以上のパラメータを設定できます。

現在サポートされている値は次のとおりです。

  • 'mac': 現在のアドレスモードに応じた、使用中の現在のアドレス。(addr_type, addr) のタプルを返します。

    アドレスタイプの詳細については gap_scan を参照してください。

    これはインターフェイスが現在アクティブな場合にのみ問い合わせできます。

  • 'addr_mode': アドレスモードを設定します。値は次のとおりです。

    名前

    動作

    0x00

    PUBLIC

    コントローラのパブリックアドレスを使用します。

    0x01

    RANDOM

    生成された静的アドレスを使用します。

    0x02

    RPA

    解決可能なプライベートアドレスを使用します。

    0x03

    NRPA

    解決不可能なプライベートアドレスを使用します。

    デフォルトでは、インターフェイスは利用可能であればPUBLICアドレスを使用し、そうでなければRANDOMアドレスを使用します。

  • 'gap_name': Generic Accessサービス(UUID 0x1800)のDevice Name characteristic(UUID 0x2a00)で使用されるGAPデバイス名を取得または設定します。これはいつでも設定でき、複数回変更できます。

  • 'rxbuf': 受信イベントを格納するために使用される内部バッファのサイズ(バイト単位)を取得または設定します。このバッファはBLEドライバ全体でグローバルであり、すべてのcharacteristicを含む、すべてのイベントの受信データを扱います。これを増やすことで、バースト的に受信するデータ(スキャン結果など)のより適切な処理や、より大きなcharacteristic値の受信が可能になります。

  • 'mtu': ATT MTU交換時に使用されるMTUを取得または設定します。結果として得られるMTUは、この値とリモートデバイスのMTUのうち小さい方になります。ATT MTU交換は(リモートデバイスが開始しない限り)自動的には行われず、gattc_exchange_mtu で手動で開始する必要があります。特定の接続のMTUを知るには _IRQ_MTU_EXCHANGED イベントを使用してください。

  • 'bond': ペアリング時にボンディングを有効にするかどうかを設定します。有効にすると、ペアリング要求に「bond」フラグが設定され、両方のデバイスにキーが保存されます。

  • 'mitm': ペアリングにMITM保護が必要かどうかを設定します。

  • 'io': このデバイスのI/O能力を設定します。

    利用可能なオプションは次のとおりです。

    定数

    能力

    _IO_CAPABILITY_DISPLAY_ONLY

    0

    表示のみ

    _IO_CAPABILITY_DISPLAY_YESNO

    1

    はい/いいえ入力付き表示

    _IO_CAPABILITY_KEYBOARD_ONLY

    2

    キーボードのみ

    _IO_CAPABILITY_NO_INPUT_OUTPUT

    3

    入力も出力もなし

    _IO_CAPABILITY_KEYBOARD_DISPLAY

    4

    キーボードと表示

  • 'le_secure': 「LE Secure」ペアリングが必要かどうかを設定します。デフォルトはfalseです(つまり「Legacy Pairing」を許可します)。

イベント処理

irq(handler: Callable[[int, Tuple], Any | None], /) None

BLEスタックからのイベントに対するコールバックを登録します。handler は2つの引数 event(以下のコードのいずれか)と data(イベント固有の値のタプル)を受け取ります。

注意: 不要なアロケーションを防ぐための最適化として、タプル内の addradv_datachar_datanotify_datauuid の各エントリは、bluetooth の内部リングバッファを指す読み取り専用のmemoryviewインスタンスであり、IRQハンドラ関数の呼び出し中のみ有効です。プログラムがIRQハンドラから戻った後にこれらの値の1つにアクセスするために保存する必要がある場合(例えばクラスインスタンスやグローバル変数に保存する場合)は、次のように bytes() または bluetooth.UUID() を使ってデータのコピーを取る必要があります:

connected_addr = bytes(addr)  # equivalently: adv_data, char_data, or notify_data
matched_uuid = bluetooth.UUID(uuid)

例えば、スキャン結果のIRQハンドラは、それが正しいデバイスかどうかを判断するために adv_data を調べ、その場合にのみアドレスデータをコピーしてプログラムの別の場所で使用する、といったことができます。また、IRQハンドラ内からデータを表示するには print(bytes(addr)) が必要になります。

ハンドラは通常、イベントコードによってディスパッチし、イベント固有のペイロードタプルをアンパックします:

def bt_irq(event, data):
    if event == _IRQ_CENTRAL_CONNECT:
        conn_handle, addr_type, addr = data
        ...
    elif event == _IRQ_SCAN_RESULT:
        addr_type, addr, adv_type, rssi, adv_data = data
        ...

すべてのイベントコード、それが配信するペイロード、および簡単な説明を以下に示します。status フィールドが言及されているイベントについて、status は成功時に 0、失敗時には実装固有の非ゼロ値になります。

定数

イベント

ペイロードタプル

_IRQ_CENTRAL_CONNECT

1

centralがこのperipheralに接続しました。

(conn_handle, addr_type, addr)

_IRQ_CENTRAL_DISCONNECT

2

centralがこのperipheralから切断しました。

(conn_handle, addr_type, addr)

_IRQ_GATTS_WRITE

3

接続中のクライアントがローカルのcharacteristicまたはdescriptorに書き込みました。新しい値を取得するには gatts_read を使用してください。

(conn_handle, attr_handle)

_IRQ_GATTS_READ_REQUEST

4

接続中のクライアントが読み取りを発行しました。読み取りを拒否するには下表の非ゼロのエラーコードを返し、受け入れるには 0 / None を返します。

(conn_handle, attr_handle)

_IRQ_SCAN_RESULT

5

アクティブスキャン中に1つのアドバタイズパケットを受信しました。

(addr_type, addr, adv_type, rssi, adv_data)

_IRQ_SCAN_DONE

6

設定された継続時間が経過したか、gap_scan(None) が呼び出されたため、現在のスキャンが終了しました。

()

_IRQ_PERIPHERAL_CONNECT

7

以前に発行された gap_connect が成功しました。

(conn_handle, addr_type, addr)

_IRQ_PERIPHERAL_DISCONNECT

8

接続中のperipheralが切断しました。

(conn_handle, addr_type, addr)

_IRQ_GATTC_SERVICE_RESULT

9

gattc_discover_services によって1つのサービスが見つかりました。

(conn_handle, start_handle, end_handle, uuid)

_IRQ_GATTC_SERVICE_DONE

10

サービス探索が完了しました。

(conn_handle, status)

_IRQ_GATTC_CHARACTERISTIC_RESULT

11

gattc_discover_characteristics によって1つのcharacteristicが見つかりました。

(conn_handle, end_handle, value_handle, properties, uuid)

_IRQ_GATTC_CHARACTERISTIC_DONE

12

characteristic探索が完了しました。

(conn_handle, status)

_IRQ_GATTC_DESCRIPTOR_RESULT

13

gattc_discover_descriptors によって1つのdescriptorが見つかりました。

(conn_handle, dsc_handle, uuid)

_IRQ_GATTC_DESCRIPTOR_DONE

14

descriptor探索が完了しました。

(conn_handle, status)

_IRQ_GATTC_READ_RESULT

15

以前に発行された gattc_read がデータを返しました。

(conn_handle, value_handle, char_data)

_IRQ_GATTC_READ_DONE

16

以前に発行された gattc_read が完了しました。

(conn_handle, value_handle, status)

_IRQ_GATTC_WRITE_DONE

17

以前に発行された gattc_write が確認応答されました。

(conn_handle, value_handle, status)

_IRQ_GATTC_NOTIFY

18

リモートサーバーが(確認応答なしの)通知を送信しました。

(conn_handle, value_handle, notify_data)

_IRQ_GATTC_INDICATE

19

リモートサーバーが(確認応答ありの)インジケーションを送信しました。

(conn_handle, value_handle, notify_data)

_IRQ_GATTS_INDICATE_DONE

20

以前に送信されたインジケーションがクライアントによって確認応答されました(またはタイムアウトしました)。

(conn_handle, value_handle, status)

_IRQ_MTU_EXCHANGED

21

ATT MTU交換が完了しました(どちらかの側によって開始されたもの)。

(conn_handle, mtu)

_IRQ_L2CAP_ACCEPT

22

リモートデバイスが、このデバイスがリッスンしているPSM上でL2CAP接続を要求しました。拒否するには非ゼロの整数を返し、受け入れるには 0 / None を返します。

(conn_handle, cid, psm, our_mtu, peer_mtu)

_IRQ_L2CAP_CONNECT

23

受信した要求を受け入れたか、発信した l2cap_connect を完了したことにより、L2CAPチャネルが確立されました。

(conn_handle, cid, psm, our_mtu, peer_mtu)

_IRQ_L2CAP_DISCONNECT

24

L2CAPチャネルが切断されました。status はクリーンな切断の場合は 0、発信接続の試行が失敗した場合は非ゼロです。

(conn_handle, cid, psm, status)

_IRQ_L2CAP_RECV

25

L2CAPチャネルにデータが到着しました。読み取るには l2cap_recvinto を呼び出してください。

(conn_handle, cid)

_IRQ_L2CAP_SEND_READY

26

False を返した以前の l2cap_send の送信が完了し、チャネルが再び使用可能になりました。status が非ゼロの場合は送信バッファがオーバーフローしたことを意味し、アプリケーションはデータを再送信する必要があります。

(conn_handle, cid, status)

_IRQ_CONNECTION_UPDATE

27

リモートデバイスが接続パラメータ(インターバル、レイテンシ、スーパービジョンタイムアウト)を更新しました。

(conn_handle, conn_interval, conn_latency, supervision_timeout, status)

_IRQ_ENCRYPTION_UPDATE

28

接続の暗号化状態が変化しました。通常はペアリングまたはボンディングの完了後に発生します。

(conn_handle, encrypted, authenticated, bonded, key_size)

_IRQ_GET_SECRET

29

スタックが保存済みのボンディングシークレットを要求しています。keyNone の場合は sec_typeindex 番目の保存値を返し、そうでない場合は指定された (sec_type, key) に関連付けられた値を返します。何も保存されていない場合は None を返します。

(sec_type, index, key)

_IRQ_SET_SECRET

30

スタックがアプリケーションにボンディングシークレットの永続化を要求しています。保存したら True を返します。

(sec_type, key, value)

_IRQ_PASSKEY_ACTION

31

ペアリングの一環としてパスキーアクションが必要です。gap_passkey を使って応答してください。可能なアクションについては下のパスキーアクション表を参照してください。

(conn_handle, action, passkey)

_IRQ_GATTS_READ_REQUEST イベントで利用可能な戻りコードは次のとおりです。

定数

意味

_GATTS_NO_ERROR

0x00

読み取りを受け入れます。

_GATTS_ERROR_READ_NOT_PERMITTED

0x02

読み取りが許可されていません。

_GATTS_ERROR_WRITE_NOT_PERMITTED

0x03

書き込みが許可されていません。

_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION

0x05

クライアントが認証されていません。

_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION

0x08

クライアントが認可されていません。

_GATTS_ERROR_INSUFFICIENT_ENCRYPTION

0x0f

リンクが暗号化されていません。

_IRQ_PASSKEY_ACTION イベントで利用可能なアクションは次のとおりです。

定数

意味

_PASSKEY_ACTION_NONE

0

アクションは不要です。

_PASSKEY_ACTION_INPUT

2

リモートデバイスに表示されているパスキーを入力するようユーザーに促します。

_PASSKEY_ACTION_DISPLAY

3

リモートデバイスが入力するための6桁のパスキーを表示します。

_PASSKEY_ACTION_NUMERIC_COMPARISON

4

パスキーがリモートデバイスに表示されているものと一致することを確認します。

ファームウェアの容量を節約するため、これらの定数は bluetooth モジュールには含まれていません。上記のリストから必要なものをプログラムに追加してください。

Broadcasterロール(アドバタイザ)

gap_advertise(interval_us: int | None, adv_data: bytes | None = None, *, resp_data: bytes | None = None, connectable: bool = True) None

指定されたインターバル(マイクロ秒単位)でアドバタイズを開始します。このインターバルは最も近い625usに切り下げられます。アドバタイズを停止するには、interval_usNone に設定します。

adv_dataresp_data には、バッファプロトコルを実装する任意の型(例: bytesbytearraystr)を指定できます。adv_data はすべてのブロードキャストに含まれ、resp_data はアクティブスキャンへの応答として送信されます。

注意: adv_data(または resp_data)が None の場合、前回の gap_advertise 呼び出しに渡されたデータが再利用されます。これにより、broadcasterは gap_advertise(interval_us) だけでアドバタイズを再開できます。アドバタイズペイロードをクリアするには、空の bytes、つまり b'' を渡します。

Observerロール(スキャナ)

gap_scan(duration_ms: int | None, interval_us: int = 1280000, window_us: int = 11250, active: bool = False, /) None

指定された継続時間(ミリ秒単位)のスキャン操作を実行します。

無期限にスキャンするには、duration_ms0 に設定します。

スキャンを停止するには、duration_msNone に設定します。

interval_uswindow_us を使用して、オプションでデューティサイクルを設定できます。スキャナは、合計 duration_ms ミリ秒の間、interval_us マイクロ秒ごとに window_us マイクロ秒だけ動作します。デフォルトのインターバルとウィンドウはそれぞれ1.28秒と11.25ミリ秒です(バックグラウンドスキャン)。

各スキャン結果に対して _IRQ_SCAN_RESULT イベントが発生し、イベントデータ (addr_type, addr, adv_type, rssi, adv_data) が渡されます。

addr_type の値はパブリックアドレスかランダムアドレスかを示します。

名前

意味

0x00

PUBLIC

パブリックデバイスアドレス。

0x01

RANDOM

ランダムアドレス(静的、RPA、またはNRPAのいずれか。タイプはアドレス自体にエンコードされています)。

adv_type の値はBluetooth仕様に対応します。

名前

意味

0x00

ADV_IND

接続可能かつスキャン可能な無指向アドバタイズ。

0x01

ADV_DIRECT_IND

接続可能な指向アドバタイズ。

0x02

ADV_SCAN_IND

スキャン可能な無指向アドバタイズ。

0x03

ADV_NONCONN_IND

接続不可能な無指向アドバタイズ。

0x04

SCAN_RSP

スキャン応答。

結果にスキャン応答を含めたい場合は、activeTrue に設定できます。

スキャンが停止すると(継続時間の終了によるもの、または明示的に停止されたもの)、_IRQ_SCAN_DONE イベントが発生します。

Centralロール

centralデバイスは、observerロールを使って(gap_scan を参照)発見したperipheral、または既知のアドレスを持つperipheralに接続できます。

gap_connect(addr_type: int | None, addr: bytes | None = None, scan_duration_ms: int = 2000, min_conn_interval_us: int | None = None, max_conn_interval_us: int | None = None, /) None

peripheralに接続します。

アドレスタイプの詳細については gap_scan を参照してください。

未完了の接続試行を早期にキャンセルするには、gap_connect(None) を呼び出します。

成功すると _IRQ_PERIPHERAL_CONNECT イベントが発生します。接続試行をキャンセルした場合は _IRQ_PERIPHERAL_DISCONNECT イベントが発生します。

デバイスは、対象デバイスからアドバタイズペイロードを受信するまで最大 scan_duration_ms 待機します。

接続インターバルは、min_conn_interval_usmax_conn_interval_us のいずれかまたは両方を使ってマイクロ秒単位で設定できます。指定しない場合はデフォルトのインターバルが選択され、通常は30000~50000マイクロ秒の範囲になります。インターバルを短くするとスループットが向上しますが、消費電力が増加します。

Peripheralロール

peripheralデバイスは、接続可能なアドバタイズを送信することが期待されます(gap_advertise を参照)。通常はGATTサーバーとして動作し、まず gatts_register_services を使ってサービスとcharacteristicを登録します。

centralが接続すると、_IRQ_CENTRAL_CONNECT イベントが発生します。

CentralおよびPeripheralロール

gap_disconnect(conn_handle: int, /) bool

指定された接続ハンドルを切断します。これは、(peripheralとして動作している場合)このデバイスに接続したcentral、または(centralとして動作している場合)このデバイスが以前に接続したperipheralのいずれかです。

成功すると _IRQ_PERIPHERAL_DISCONNECT または _IRQ_CENTRAL_DISCONNECT イベントが発生します。

接続ハンドルが接続されていなかった場合は False を、そうでない場合は True を返します。

GATTサーバー

GATTサーバーは登録されたサービスのセットを持ちます。各サービスはcharacteristicを含むことができ、それぞれが値を持ちます。characteristicはまたdescriptorを含むことができ、それ自体が値を持ちます。

これらの値はローカルに保存され、サービス登録時に生成される「value handle」によってアクセスされます。また、リモートのクライアントデバイスから読み取りや書き込みを行うこともできます。さらに、サーバーは接続ハンドルを介して、接続中のクライアントにcharacteristicを「通知」できます。

centralまたはperipheralのいずれのロールのデバイスもGATTサーバーとして機能できますが、ほとんどの場合、peripheralデバイスがサーバーとして動作することがより一般的です。

characteristicとdescriptorのデフォルトの最大サイズは20バイトです(デフォルトのATT MTUである23バイトから3バイトのATTヘッダを引いたもの。ネゴシエートされたMTUが大きくなっても、それだけではこの制限は上がりません)。クライアントがそれらに書き込んだものは、この長さに切り詰められます。ただし、ローカルでの書き込みは最大サイズを増やすため、特定のcharacteristicへのクライアントからのより大きな書き込みを許可したい場合は、登録後に gatts_write を使用してください。例: gatts_write(char_handle, bytes(100))

gatts_register_services(services_definition: Sequence[Sequence], /) Sequence[Sequence[int]]

指定されたサービスでサーバーを設定し、既存のサービスを置き換えます。

services_definitionサービス のリストです。各 サービス は、UUIDと characteristic のリストを含む2要素のタプルです。

characteristic は、UUID、flags 値、およびオプションで descriptor のリストを含む2要素または3要素のタプルです。

descriptor は、UUIDと flags 値を含む2要素のタプルです。

flags は、以下で定義されるフラグのビット単位ORの組み合わせです。これらはcharacteristic(またはdescriptor)の動作と、セキュリティおよびプライバシーの要件の両方を設定します。

戻り値はタプルのリスト(サービスごとに1要素)で、各要素はvalue handleです。characteristicとdescriptorのハンドルは、定義された順序で同じタプルにフラット化されます。

次の例は2つのサービス(Heart RateとNordic UART)を登録します:

bt = bluetooth.BLE()
bt.active(True)

# Heart Rate service: one Heart Rate Measurement characteristic.
HR_SERVICE = (
    bluetooth.UUID(0x180D),
    (
        (bluetooth.UUID(0x2A37),
         bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY),
    ),
)

# Nordic UART service: a TX characteristic the client subscribes
# to for notifications, and an RX characteristic it writes to.
UART_SERVICE = (
    bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E'),
    (
        (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'),
         bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY),
        (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'),
         bluetooth.FLAG_WRITE),
    ),
)

((hr,), (tx, rx)) = bt.gatts_register_services(
    (HR_SERVICE, UART_SERVICE),
)

3つのvalue handle(hrtxrx)は、gatts_readgatts_writegatts_notifygatts_indicate で使用できます。

注意: サービスを登録する前に、アドバタイズを停止する必要があります。

characteristicとdescriptorで利用可能なフラグは次のとおりです。

定数

意味

_FLAG_BROADCAST

0x0001

characteristicはブロードキャストできます。

_FLAG_READ

0x0002

クライアントは値を読み取れます。

_FLAG_WRITE_NO_RESPONSE

0x0004

クライアントは応答を期待せずに書き込めます。

_FLAG_WRITE

0x0008

クライアントは確認応答ありで書き込めます。

_FLAG_NOTIFY

0x0010

サーバーは通知(確認応答なし)を送信できます。

_FLAG_INDICATE

0x0020

サーバーはインジケーション(確認応答あり)を送信できます。

_FLAG_AUTHENTICATED_SIGNED_WRITE

0x0040

クライアントは署名付き書き込みを発行できます。

_FLAG_AUX_WRITE

0x0100

拡張プロパティ: キュー付き/信頼性のある書き込みが許可されます。

_FLAG_READ_ENCRYPTED

0x0200

読み取りには暗号化されたリンクが必要です。

_FLAG_READ_AUTHENTICATED

0x0400

読み取りには認証された(MITM保護された)リンクが必要です。

_FLAG_READ_AUTHORIZED

0x0800

読み取りにはアプリケーションレベルの認可が必要です。

_FLAG_WRITE_ENCRYPTED

0x1000

書き込みには暗号化されたリンクが必要です。

_FLAG_WRITE_AUTHENTICATED

0x2000

書き込みには認証された(MITM保護された)リンクが必要です。

_FLAG_WRITE_AUTHORIZED

0x4000

書き込みにはアプリケーションレベルの認可が必要です。

上記のイベント定数と同様に、これらのフラグも bluetooth モジュールでは提供されていません。必要なものをプログラムにコピーしてください。

gatts_read(value_handle: int, /) bytes

このハンドルのローカル値(gatts_write によって、またはリモートクライアントによって書き込まれたもの)を読み取ります。

gatts_write(value_handle: int, data: bytes, send_update: bool = False, /) None

このハンドルのローカル値を書き込みます。これはクライアントから読み取ることができます。

send_updateTrue の場合、サブスクライブしているクライアントは、この書き込みについて通知(またはインジケーション。クライアントが何にサブスクライブしているか、およびcharacteristicがどの操作をサポートしているかによる)を受け取ります。

gatts_notify(conn_handle: int, value_handle: int, data: bytes | None = None, /) None

接続中のクライアントに通知要求を送信します。

dataNone(デフォルト)の場合、現在のローカル値(gatts_write で設定されたもの)が送信されます。

そうでない場合、dataNone でなければ、その値が通知の一部としてクライアントに送信されます。ローカル値は変更されません。

注意: 通知は、このcharacteristicに対するクライアントのサブスクリプション状態に関係なく送信されます。

gatts_indicate(conn_handle: int, value_handle: int, data: bytes | None = None, /) None

接続中のクライアントにインジケーション要求を送信します。

dataNone(デフォルト)の場合、現在のローカル値(gatts_write で設定されたもの)が送信されます。

そうでない場合、dataNone でなければ、その値がインジケーションの一部としてクライアントに送信されます。ローカル値は変更されません。

確認応答時(または失敗時、例: タイムアウト)に、_IRQ_GATTS_INDICATE_DONE イベントが発生します。

注意: インジケーションは、このcharacteristicに対するクライアントのサブスクリプション状態に関係なく送信されます。

gatts_set_buffer(value_handle: int, len: int, append: bool = False, /) None

値の内部バッファサイズをバイト単位で設定します。これにより、受信可能な書き込みの最大サイズが制限されます。デフォルトは20バイトです(デフォルトのATT MTUである23から3バイトのATTヘッダを引いたもの)。

appendTrue に設定すると、すべてのリモート書き込みが、現在の値を置き換えるのではなく追記するようになります。この方法で最大 len バイトまでバッファできます。gatts_read を使用すると、読み取り後に値がクリアされます。この機能は、Nordic UART Serviceのようなものを実装する際に役立ちます。

GATTクライアント

GATTクライアントは、リモートのGATTサーバー上のcharacteristicを発見し、読み取り/書き込みできます。

centralロールのデバイスがGATTクライアントとして動作するのがより一般的ですが、接続してきたcentralに関する情報を発見するために(例えばdevice informationサービスからデバイス名を読み取るために)、peripheralがクライアントとして動作することも可能です。

gattc_discover_services(conn_handle: int, uuid: UUID | None = None, /) None

接続中のサーバーにそのサービスを問い合わせます。

オプションでサービス uuid を指定して、そのサービスのみを問い合わせることができます。

発見された各サービスに対して _IRQ_GATTC_SERVICE_RESULT イベントが発生し、完了時に _IRQ_GATTC_SERVICE_DONE が続きます。

gattc_discover_characteristics(conn_handle: int, start_handle: int, end_handle: int, uuid: UUID | None = None, /) None

接続中のサーバーに、指定された範囲内のcharacteristicを問い合わせます。

オプションでcharacteristic uuid を指定して、そのcharacteristicのみを問い合わせることができます。

start_handle=1end_handle=0xffff を渡すと、GATTのアトリビュートハンドルの全範囲をカバーするため、この組み合わせは実質的にリモートデバイス上のすべてのサービスを検索します。

発見された各characteristicに対して _IRQ_GATTC_CHARACTERISTIC_RESULT イベントが発生し、完了時に _IRQ_GATTC_CHARACTERISTIC_DONE が続きます。

gattc_discover_descriptors(conn_handle: int, start_handle: int, end_handle: int, /) None

接続中のサーバーに、指定された範囲内のdescriptorを問い合わせます。

発見された各descriptorに対して _IRQ_GATTC_DESCRIPTOR_RESULT イベントが発生し、完了時に _IRQ_GATTC_DESCRIPTOR_DONE が続きます。

gattc_read(conn_handle: int, value_handle: int, /) None

接続中のサーバーに、指定されたcharacteristicまたはdescriptorハンドルに対するリモート読み取りを発行します。

値が利用可能になると _IRQ_GATTC_READ_RESULT イベントが発生し、完了時に _IRQ_GATTC_READ_DONE が続きます。

gattc_write(conn_handle: int, value_handle: int, data: bytes, mode: int = 0, /) None

接続中のサーバーに、指定されたcharacteristicまたはdescriptorハンドルに対するリモート書き込みを発行します。

引数 mode は書き込みの動作を指定します。現在サポートされている値は次のとおりです。

  • mode=0(デフォルト)は応答なし書き込みです。書き込みはリモートサーバーに送信されますが、確認は返されず、イベントも発生しません。

  • mode=1 は応答あり書き込みです。リモートサーバーに対して、データを受信したことを示す応答/確認応答を送信するよう要求します。

リモートサーバーから応答を受信すると、_IRQ_GATTC_WRITE_DONE イベントが発生します。

gattc_exchange_mtu(conn_handle: int, /) None

BLE.config(mtu=value) で設定された希望MTUを使用して、接続中のサーバーとMTU交換を開始します。

MTU交換が完了すると _IRQ_MTU_EXCHANGED イベントが発生します。

MTU交換は通常centralによって開始されますが、NimBLEは両方のロールをサポートします。

L2CAPコネクション指向チャネル

この機能により、2つのBLEデバイス間でソケットのようなデータ交換が可能になります。デバイスがGAP経由で接続されると、どちらのデバイスも数値のPSM(Protocol/Service Multiplexer)上で相手の接続をリッスンできます。

一度にアクティブにできるL2CAPチャネルは1つだけです(つまり、リッスン中に接続することはできません)。

アクティブなL2CAPチャネルは、それが確立された接続ハンドルとCID(チャネルID)によって識別されます。

コネクション指向チャネルには、クレジットベースのフロー制御が組み込まれています。デバイスが共有MTUをネゴシエートするATTとは異なり、リッスン側と接続側のデバイスはそれぞれ独立したMTUを設定します。これは、l2cap_recvinto で完全に消費される前に、リモートデバイスが送信できる未処理データの最大量を制限します。

l2cap_listen(psm: int, mtu: int, /) None

指定された psm 上で、ローカルMTUを mtu に設定して、L2CAPチャネル要求の受信をリッスンし始めます。

リモートデバイスが接続を開始すると _IRQ_L2CAP_ACCEPT イベントが発生し、リッスン中のサーバーは(非ゼロの整数を返すことで)受信接続を拒否する機会が与えられます。

接続が受け入れられると _IRQ_L2CAP_CONNECT イベントが発生し、サーバーはチャネルID(CID)およびローカルとリモートのMTUを取得できます。

注意: 現在のところ、リッスンを停止することはできません。

l2cap_connect(conn_handle: int, psm: int, mtu: int, /) None

指定された psm 上で、ローカルMTUを mtu に設定して、リッスン中のピアに接続します。

接続に成功すると _IRQ_L2CAP_CONNECT イベントが発生し、クライアントはCIDおよびローカルとリモート(ピア)のMTUを取得できます。

接続に失敗すると、非ゼロのステータスを伴う _IRQ_L2CAP_DISCONNECT イベントが発生します。

l2cap_disconnect(conn_handle: int, cid: int, /) None

指定された conn_handlecid を持つアクティブなL2CAPチャネルを切断します。

l2cap_send(conn_handle: int, cid: int, buf: bytes, /) bool

conn_handlecid で識別されるL2CAPチャネル上で、指定された buf(バッファプロトコルをサポートする必要があります)を送信します。

バッファは両方の制限を満たす必要があります。リモート(ピア)のMTUを超えてはならず、かつローカルMTUの2倍を超えてもなりません。

チャネルが「ストール」した場合は False を返します。これは、_IRQ_L2CAP_SEND_READY イベントを受信するまで l2cap_send を再度呼び出してはならないことを意味します(このイベントは、リモートデバイスがより多くのクレジットを付与したとき、通常はデータを受信して処理した後に発生します)。

l2cap_recvinto(conn_handle: int, cid: int, buf: Any | None, /) int

指定された conn_handlecid から、提供された buf(バッファプロトコルをサポートする必要があります。例: bytearrayまたはmemoryview)にデータを受信します。

チャネルから読み取ったバイト数を返します。

bufNone の場合、利用可能なバイト数を返します。

注意: _IRQ_L2CAP_RECV イベントを受信した後、アプリケーションは受信バッファに利用可能なバイトがなくなるまで(通常はリモート(ピア)のMTUのサイズまで)l2cap_recvinto を呼び出し続ける必要があります。

受信バッファが空になるまで、リモートデバイスにはそれ以上のチャネルクレジットが付与されず、これ以上データを送信できなくなります。

ペアリングとボンディング

ペアリングにより、シークレットの交換を通じて接続を暗号化し認証できます(パスキー認証によるオプションのMITM保護付き)。

ボンディングは、それらのシークレットを不揮発性ストレージに保存するプロセスです。ボンディングされると、デバイスは保存された identity resolving key(IRK)に基づいて、別のデバイスからの解決可能なプライベートアドレス(RPA)を解決できます。ボンディングをサポートするには、アプリケーションが _IRQ_GET_SECRET および _IRQ_SET_SECRET イベントを実装する必要があります。

gap_pair(conn_handle: int, /) None

リモートデバイスとのペアリングを開始します。

これを呼び出す前に、iomitmle_securebond の各設定オプションが(config を介して)設定されていることを確認してください。

ペアリングに成功すると _IRQ_ENCRYPTION_UPDATE イベントが発生します。

gap_passkey(conn_handle: int, action: int, passkey: int, /) None

指定された conn_handleaction に対する _IRQ_PASSKEY_ACTION イベントに応答します。passkey の意味は action に依存します(さらにそれは設定されたI/O能力に依存します)。

アクション

必要な passkey 応答

_PASSKEY_ACTION_INPUT

ユーザーがリモートデバイスから読み取るパスキー。

_PASSKEY_ACTION_DISPLAY

ユーザーに表示される、ローカルで生成された6桁のランダムなパスキー。

_PASSKEY_ACTION_NUMERIC_COMPARISON

_IRQ_PASSKEY_ACTION イベントで表示されたパスキーを受け入れるには 1、ペアリングをキャンセルするには 0

class UUID

class bluetooth.UUID(value: int | bytes | str, /)

指定された value でUUIDインスタンスを作成します。Bluetoothは3つのUUID幅を使用し、UUID はそのいずれも受け付けます。

UUID幅

受け付けられる value の型

16ビット

int または2バイトのバッファ(リトルエンディアン)

UUID(0x2908) または UUID(b'\x08\x29')

32ビット

4バイトのバッファ(リトルエンディアン)

UUID(b'\x08\x29\x00\x00')

128ビット

16バイトのバッファまたはハイフン区切りの文字列

UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')

16ビットおよび32ビットのUUIDは通常SIGによって割り当てられた識別子です(Bluetooth assigned numbers を参照)。128ビットのUUIDは通常ベンダー定義です。