プロトコル仕様

bleRPCはBLE GATTの上に階層化されたプロトコルスタックを使用します。コマンド層はProtocol BuffersペイロードをRPCメタデータでカプセル化し、オプションの暗号化層はシリアライズされたコマンドを暗号化し、コンテナ層はMTUサイズのパケットに分割してBLE伝送します。

接続セットアップシーケンス

RPC呼び出しを行う前に、セントラルはペリフェラルとの短いセットアップシーケンスを実行します。これは全体のタイムラインであり、各ステップは以下のセクション(および鍵交換については暗号化)で詳しく説明します。

コマンド層

コマンド層は、Protocol BuffersでエンコードされたデータをRPCメタデータとともに CommandPacket にまとめます。コマンドは名前(ASCII文字列)で識別され、柔軟で人間が読みやすいディスパッチを可能にします。

コマンドフォーマット

T
1 bit
reserved
7 bits
cmd_name_len
8 bits
cmd_name
variable
data_len
16 bits (LE)
data
variable
フィールドビット数説明
type10 = リクエスト、1 = レスポンス
reserved7ゼロ埋め
cmd_name_len8コマンド名の長さ(バイト)
cmd_name可変ASCIIコマンド名(例: echoflash_read
data_len16protobufデータの長さ(バイト、リトルエンディアン)
data可変Protocol Buffersでエンコードされたペイロード

コマンド検出

コードジェネレーターは、次の2つの方法のいずれかで.protoファイルからコマンドを導出します:

メッセージペアコマンド名
EchoRequest + EchoResponseecho
FlashReadRequest + FlashReadResponseflash_read
DataWriteRequest + DataWriteResponsedata_write

ストリーミングコマンドは別途登録されます — サービスブロック内のストリーミングrpcメソッドを介するか、proto/streaming.txtにリストアップする(例: counter_stream p2ccounter_upload c2p)かのいずれかです。これらは、単純なリクエスト/レスポンスメソッドの代わりに、専用のストリーミングAPI(ストリーミングを参照)を生成します。

暗号化層

暗号化はオプションです。セッションが有効な場合(暗号化を参照)、シリアライズされたコマンドは、コンテナ層に渡される前にAES-128-GCMで暗号化されます。暗号化されたペイロードは[counter:4][ciphertext:N][tag:16]であり、20バイトのオーバーヘッド(4バイトのカウンター + 16バイトのGCMタグ)を持ちます。これは、プレーンテキストのコマンドとまったく同じようにコンテナに分割されます。

カウンターは、AES-GCMのnonceとリプレイ防止の両方を兼ねます。ハンドシェイク、鍵導出、nonceの構成、リプレイ規則については暗号化を参照してください。

コンテナ層

コンテナ層は、大きなペイロードをMTUサイズのパケットに分割し、受信側で再組み立てします。各コンテナは追跡と順序付けのためにトランザクションIDとシーケンス番号を持ちます。

コンテナフォーマット

すべてのマルチバイトフィールドはリトルエンディアンです。

最初のコンテナ (type=0b00)

トランザクションの最初のコンテナには、ペイロードの合計長が含まれます:

transaction_id
8 bits
sequence_number
8 bits
type
2
control_cmd
4
reserved
2
total_length
16 bits (LE)
payload_len
8 bits
payload
variable
フィールドビット数説明
transaction_id8このリクエスト/レスポンスペアの一意のID。トランザクションごとにリセットされます。
sequence_number8コンテナ送信ごとにインクリメント。トランザクションごとにリセットされます。
type20b00 = 最初
control_cmd40x0(データコンテナでは未使用)
reserved2ゼロ埋め
total_length16全コンテナにわたるペイロードの合計サイズ(バイト、リトルエンディアン)
payload_len8このコンテナ内のペイロードサイズ(バイト)
payload可変コマンドデータのフラグメント

ヘッダーサイズ: 6バイト(transaction_id + sequence_number + flags + total_length + payload_len)

後続コンテナ (type=0b01)

継続コンテナはtotal_lengthを省略します:

transaction_id
8 bits
sequence_number
8 bits
type
2
control_cmd
4
reserved
2
payload_len
8 bits
payload
variable

ヘッダーサイズ: 4バイト(total_lengthフィールドなし)

バイト2のビットフィールド詳細

各コンテナの3バイト目は、タイプ、コントロールコマンド、および予約ビットをエンコードします:

type
bits 7-6
control_cmd
bits 5-2
reserved
bits 1-0

コンテナ分割の例

MTU=247(ATTオーバーヘッド後の利用可能サイズ244)で500バイトのコマンドペイロードの場合:

コンテナタイプヘッダーペイロード合計
1FIRST6バイト238バイト244バイト
2SUBSEQUENT4バイト240バイト244バイト
3SUBSEQUENT4バイト22バイト26バイト

ペイロード合計: 500バイト(238 + 240 + 22)

最大ペイロード

単一トランザクションは2つの制限で制約されます。sequence_numberは8ビットであるため、約255コンテナに制限されます。一般的なMTU 247(後続コンテナあたり240バイト)の場合、これは実用的な最大値として約60 KBになります。また、16ビットのtotal_lengthフィールドにより、絶対的な上限として65,535バイトが課されます。より大きな転送には、複数のリクエスト/レスポンスサイクルを使用してください。

BLEトランスポート

すべての通信は単一のGATT Characteristicを使用します:

MTUはBLE ATT MTU Exchangeプロシージャにより自動的に合意形成されます。アプリケーションは合意形成されたMTU(ATTオーバーヘッドの3バイトを引いた値)を使用して、コンテナペイロードの最大サイズを決定

デフォルトタイムアウトは100msで、タイムアウト制御コンテナで設定可能

リクエスト/レスポンスフロー

完全なRPC呼び出しは、コマンド層でのエンコード、コンテナ層での分割、BLE伝送、そして受信側での逆処理で構成されます:

制御コンテナ

制御コンテナ(type=0b11)は、アプリケーションデータの代わりにプロトコルレベルのコマンドを送信します。

タイムアウト共有 (control_cmd=0x1)

ペリフェラルが処理タイムアウトをセントラルに伝えることができます。

リクエスト (Central → Peripheral)

フィールド
type0b11(制御)
control_cmd0x1
payload_len0x00

レスポンス (Peripheral → Central)

フィールド
type0b11(制御)
control_cmd0x1
payload_len0x02
payloadtimeout_ms(16ビットLE、ミリ秒)

機能共有 (control_cmd=0x4)

ペリフェラルがバッファ制約と機能フラグをセントラルに伝えることができます。

リクエスト (Central → Peripheral)

フィールド
type0b11(制御)
control_cmd0x4
payload_len0x06
payload[0:2]max_request_payload_size(16ビットLE、通常0)
payload[2:4]max_response_payload_size(16ビットLE、通常0)
payload[4:6]flags(16ビットLE、通常0)

レスポンス (Peripheral → Central)

フィールド
type0b11(制御)
control_cmd0x4
payload_len0x06
payload[0:2]max_request_payload_size(16ビットLE)
payload[2:4]max_response_payload_size(16ビットLE)
payload[4:6]flags(16ビットLE) — ビット0: 暗号化サポート

機能ペイロードは常に6バイトです。オプション機能を持たないペリフェラルは、単にflags = 0x0000を報告します。

ストリーム終了 (control_cmd=0x2, 0x3)

ストリーミングシーケンスの終了を通知します。どちら側からでもストリームを終了できます。

control_cmd方向説明
0x2Central → PeripheralCentralがアップロードストリームを終了
0x3Peripheral → CentralPeripheralがダウンロードストリームを終了

どちらもpayload_len=0x00(ペイロードなし)

エラー通知 (control_cmd=0x5)

エラー発生時(例: レスポンスがバッファ制限を超えた場合)にペリフェラルから送信されます。

フィールド
type0b11(制御)
control_cmd0x5
payload_len0x01
payload[0]エラーコード

エラーコード:

鍵交換 (control_cmd=0x6)

暗号化セッションを確立するための鍵交換ハンドシェイクペイロードを送信します。ペリフェラルが対応機能のflagsフィールドで暗号化サポートを通知した場合に使用されます。

フィールド
type0b11(制御)
control_cmd0x6
payload_len可変
payload鍵交換ステップデータ(暗号化を参照)

ハンドシェイクを完了するために4つのコンテナ(ステップ1〜4)が交換されます。完了後、すべての後続データコンテナは暗号化されたペイロードを送信します。

ストリーミング

bleRPCは、単純なリクエスト/レスポンスに加えて、2つのストリーミングパターンをサポートしています:

Peripheral → Central ストリーム(サーバーストリーミング)

1つのリクエストが複数のレスポンスをトリガーします。ストリームはSTREAM_END_P2C制御コンテナで終了します。

Central → Peripheral ストリーム(クライアントストリーミング)

複数のリクエストが送信され、STREAM_END_C2P制御コンテナが続きます。ペリフェラルは最終メッセージで応答します。