Bluetooth Low Energyのデータパケット



Bluetooth Low Energyのデータパケット

このトピックでは、EchoデバイスとガジェットがBluetooth Low Energy(BLE)経由のデータ交換に使用するパケットの形式について説明します。

Bluetoothに関連するAlexa Gadgets Toolkitの問題については、既知の問題ページを参照してください。

概念

EchoデバイスとガジェットがBLE経由で交換するパケットについて理解するには、ストリームとトランザクションの概念について学んでおく必要があります。

ストリーム

ストリームは、パケットをさまざまな種類に分割する方法です。ガジェットでは、次のストリームをサポートする必要があります。

  • 制御ストリーム – Echoデバイスとガジェットはこのストリームによって通信できるようになります。これらのパケットのペイロードは、ガジェットのコンフィギュレーションを管理したり、最初のハンドシェイク時にデバイス情報を交換したりします。
  • Alexaストリーム – Echoデバイスとガジェットはこのストリームを使って、すべてのAlexa Gadgets Toolkitインターフェースのディレクティブとイベントを送信します。
  • OTA(無線)ストリーム – EchoデバイスとガジェットはOTAアップデートプロセスでこのストリームを使い、ガジェットファームウェアをアップデートします。

どの時点においても、存在するのは1つの制御ストリーム、1つのAlexaストリーム、1つのOTAストリーム(該当する場合)だけです。各パケットはこれらのストリームのいずれかに属します。どのストリームに属するかは、パケットヘッダーのストリームIDフィールドで指定します。ストリームIDにより、受信側(ガジェットまたはEchoデバイス)はパケットのペイロードを解釈できます。

トランザクション

トランザクションは、処理対象データの論理チャンクです。トランザクションは、MTUサイズに応じて、1つまたは複数のデータパケットで構成されます。トランザクションの種類(各パケットヘッダーのオフセット12)により、パケットがトランザクションの最初なのか、最後なのか、中間なのかを指定します。トランザクションIDとストリームIDの組み合わせにより、メッセージを一意に識別できます。

パケットの形式

パケットはバイナリーで、各フィールドはビッグエンディアンで格納されます。各パケットは、ヘッダーペイロードで構成されます。ヘッダーにはストリームID、トランザクションIDなどが含まれます。ペイロードの形式はストリームの種類(制御ストリームかAlexaストリームか)によって異なります。

確認(ACK)パケット

Echoデバイスがリクエストした場合、ガジェットはトランザクションの最終パケットへの応答として、Echo deviceにACKパケットを送信する必要があります。ACKパケットの全体的な構成はほかのパケットと同じですが、一部のフィールドにはACKパケットの詳細に記載した値をセットする必要があります。

ガジェットがトランザクションでACKが必要かどうかを判断するには、トランザクションの最終パケットのヘッダーで、ACKフラグ(オフセット14)を確認する必要があります。トランザクションの最終パケットかどうかは、パケットのトランザクションの種類(オフセット12)で判断できます。複数パケットの場合は10、単一パケットの場合は00です。

ACKパケットは、確認しているトランザクションと同じストリームIDとトランザクションIDを使用する必要があります。制御ストリーム、Alexaストリームはいずれも、ACKパケットをサポートします。現時点では、EchoデバイスからガジェットにACKパケットを送信するようリクエストすることはできますが、その逆はできません。

各パケットにはヘッダーがあります。パケットヘッダーのサイズは、次の2つの要因によって変わります。

  • トランザクション内でのパケットの位置 – トランザクションの最初のパケットは、ヘッダーに追加の24ビット(予約されたフィールドとトランザクション長のフィールド)を含みます。
  • ペイロード長のフィールド拡張 – ヘッダーのペイロード長フィールドは、拡張なし(8ビット)、拡張あり(16ビット)のいずれかになります。1ビットのパケット長拡張フィールドは、ペイロード長が拡張されているかどうかを示します。

以下は、ペイロード長フィールドを拡張しない場合とした場合のヘッダーを図式化したものです。図のとおり、一部のフィールドはトランザクションの最初のパケットにのみ存在します。MTUや総トランザクション長の異なるAlexa.Discovery.Discoverディレクティブヘッダーの例については、パケットシーケンスの例を参照してください。

ヘッダー(ペイロード長フィールドの拡張なし)

Alexa Gadgets Toolkitパケットヘッダー(ペイロード長フィールドの拡張なし)

ヘッダー(ペイロード長フィールドの拡張あり)

Alexa Gadgets Toolkitパケットヘッダー(ペイロード長フィールドの拡張あり)

ヘッダーのフィールドは次のとおりです。

オフセット(ビット) 長さ(ビット) 説明
0 4

ストリームIDです。

0000: 制御ストリーム
0110: Alexaストリーム
0010: OTAストリーム

4 4

トランザクションIDです。

1つのストリームIDのトランザクション内では常に一意の数字となります。別のストリームに属するパケットであれば、同時に同じトランザクションIDを使うことができます。

8 4 シーケンス番号です。長さが4ビットのため、任意の時点で最大16パケットのシーケンス指定をサポートできます。

シーケンス番号は戻すことができます。パケットの順序がずれた場合(つまりシーケンス番号の順序がずれた場合)、トランザクションを中断する必要があります。たとえば、16の次が0の場合は正しい順序ですが、16の次が10の場合は順序がずれています。

番号は、トランザクションのたびに増えていきます。

12 2

トランザクションの種類です。パケットがトランザクションのどの位置にあるかを示します。単一パケットのトランザクションの種類とプロトコルは、トランザクションの最初のパケットで定義されます。

00: トランザクションの最初のパケット、単一パケットトランザクションの場合は唯一のパケットを表します。
01: トランザクションの続きのパケット(最初と最後以外のパケット)を表します。
10: トランザクションの最終パケットを表します。
11: 制御パケットです。現時点では、制御パケットの種類はACKパケットのみです。

14 1

確認(ACK)フラグです。

0: トランザクションの別のパケットでこのビットが1にセットされている場合を除き、トランザクションの最終パケットの応答としてガジェットがACKパケットを送信する必要はありません。
1: ガジェットは、トランザクションの最終パケットへの応答としてACKパケットを送信する必要があります。

15 1

パケット長を拡張するかどうかを示します。

このビットは、ペイロードフィールドの長さを表します。このビットがセットされない場合、8ビットになります。パケット長拡張フィールドは、特定のMTUがどれだけのデータで埋まっているかによって動的に変化します。つまり、トランザクションの特定のパケットでパケット長拡張フィールドが1にセットされ、別のパケットでは0にセットされる場合もあります。

0: パケットのペイロード長は8ビットです。
1: パケットのペイロード長は16ビットです。

16 8 予約済みです。トランザクションの最初のパケットにのみ存在します。

0: 現時点で唯一の設定可能な値です。

24 16 総トランザクション長です。トランザクションの最初のパケットにのみ存在します。単一パケットのトランザクションにもこのフィールドはあります。 トランザクションの長さ(バイト)です。
40または16 8または16

ペイロード長です。ペイロード長はパケットごとに異なります。

このフィールドのオフセットと長さは、前述の2つの要因によって変わります。

トランザクション内のパケット位置 – トランザクションの最初のパケットでは、オフセットは40ビット目になります。トランザクションの後続のパケットでは、オフセットは16ビット目になります。

ペイロード長フィールドの拡張 – ヘッダーの前方にあるペイロード長拡張ビットの値によって異なります。このビットがセットされていない場合、ペイロード長フィールドは8ビットになります。このビットがセットされている場合、ペイロード長フィールドは16ビットになります。

ペイロードの長さ(バイト)です。

ペイロードの種類

各ペイロードは、proto3の構文を使ったプロトコルバッファー形式です。ペイロードの種類は、ストリームの種類によって次の2つのいずれかになります。

制御ストリームのペイロード

制御ストリームによって、Echoデバイスとガジェットの通信が可能になります。各制御ストリームのメッセージは、ペイロードを含むエンベロープで構成されます。

エンベロープ

制御ストリームペイロードのエンベロープ(プロトコルバッファー形式)は、次のようになります。

message ControlEnvelope {
    Command command = 1;
 
    oneof payload {
        // 応答
        Response response = 9;
 
        // メッセージ
        // ...
    }
}

enum Command {
    NONE = 0;
    GET_DEVICE_INFORMATION = 20;
    GET_DEVICE_FEATURES = 28;
    UPDATE_COMPONENT_SEGMENT = 94;
    APPLY_FIRMWARE = 95;
}

応答

ガジェットがEchoデバイスからサポート対象の制御ストリームメッセージを受信すると、ガジェットは応答として制御ストリームメッセージを送信する必要があります。応答メッセージのペイロードは、そのメッセージに関連するコマンドによって異なります。ガジェットが理解できない制御ストリームを受信した場合、UNSUPPORTED結果コードで応答してください。

message Response {
    ErrorCode error_code = 1;
 
    oneof payload {
        // 任意のデータ
    }
}

enum ErrorCode {
    SUCCESS = 0;
    UNKNOWN = 1;    
    UNSUPPORTED = 3;
}

制御ストリーム固有のペイロード

ガジェットとEchoデバイスが交換する制御ストリームパケットは、以下のいずれかのペイロードを持ちます。

メッセージ コマンドID 送信元 用途

DeviceInformationコマンド

20

Echoデバイス

ハンドシェイク

DeviceInformation応答

20

ガジェット

ハンドシェイク

DeviceFeaturesコマンド

28

Echoデバイス

ハンドシェイク

DeviceFeatures応答

28

ガジェット

ハンドシェイク

UpdateComponentSegmentコマンド

94

Echoデバイス

OTA

UpdateComponentSegment応答

94

ガジェット

OTA

ApplyFirmwareコマンド

95

Echoデバイス

OTA

ApplyFirmware応答

95

ガジェット

OTA

DeviceInformationコマンド(コマンドID 20)

ハンドシェイク中にデバイス情報をガジェットに照会するには、Echoデバイスがコマンドに20(GET_DEVICE_INFORMATION)をセットしてガジェットに制御エンベロープを送信します。このパケットの例については、Bluetooth Low Energyハンドシェイクのサンプルコードを参照してください。

DeviceInformation応答

ハンドシェイク中にEchoデバイスからデバイス情報を照会されると、ガジェットはデバイス情報を含むペイロードを持つ制御エンベロープのパケットで応答する必要があります。

このパケットの例については、Bluetooth Low Energyハンドシェイクのサンプルコードを参照してください。

message DeviceInformation {
    string serial_number = 1;
    string name = 2;
    repeated Transport supported_transports = 3;
    string device_type = 4;
}

enum Transport {
   BLUETOOTH_LOW_ENERGY = 0;
}
フィールド名 説明 必須

serial_number

ガジェットに一意のデバイスシリアル番号(DSN)です。

検出応答のendpointIdと同じ文字列となります。

name

ガジェットのユーザーフレンドリー名です。この名前はユーザーが変更できます。

検出応答のfriendlyNameと同じ文字列となります。

supported_transports

ガジェットがサポートする転送方法のコレクションです。このフィールドにより、Echoデバイスはガジェットとの通信に最適な転送方法を選択できます。

サポートされる転送方法のリストです。現在、この値は[BLUETOOTH_LOW_ENERGY]です。

device_type

Amazonが割り当てた一意のデバイスタイプです。

検出応答のamazonDeviceTypeと同じ文字列となります。

DeviceFeaturesコマンド(コマンドID 28)

ハンドシェイク中にデバイスの機能をガジェットに照会するには、Echoデバイスがコマンドに28(GET_DEVICE_FEATURES)をセットしてガジェットに制御エンベロープを送信します。このパケットの例については、Bluetooth Low Energyハンドシェイクのサンプルコードを参照してください。

DeviceFeatures応答

Echoデバイスからガジェットのデバイス機能を照会したとき、ガジェットはサポートする機能を記載したパケットで応答する必要があります。このパケットの例については、Bluetooth Low Energyハンドシェイクのサンプルコードを参照してください。

message DeviceFeatures {
 uint64 features = 1;
 uint64 device_attributes = 2;
}

フィールド名 説明 必須

features

ガジェットがサポートする機能です。

uint64のビット定義は次のとおりです。

オフセット0: ガジェットがAlexa Gadgets Toolkit機能セットをサポートする場合、1にセットします。

オフセット1: ガジェットがOTAアップデートをサポートする場合、1にセットします。

オフセット20にセットします。

オフセット30にセットします。

オフセット41にセットします。

オフセット5~630にセットします。

device_attributes

予約済みです。

0にセットしたuint64です。

UpdateComponentSegmentコマンド(コマンドID 94)

AlexaサービスがガジェットにOTAアップデートが必要と判断した場合、EchoデバイスはガジェットにUpdateComponentSegmentメッセージを送信します。このパケットの例については、Bluetooth Low Energyハンドシェイクのサンプルコードを参照してください。

message UpdateComponentSegment {
    string component_name = 1; 
    uint32 component_offset = 2; 
    uint32 segment_size = 3; 
    string segment_signature = 4; 
}
フィールド名 説明 必須

component_name

コンポーネント名です。

文字列です。

component_offset

コンポーネントのオフセット(バイト)です。

0にセットしたuint64です。

segment_size

ファームウェアイメージのサイズ(バイト)です。

ファームウェアイメージのバイト数の値をセットしたuint32です。

segment_signature

ファームウェアイメージのSHA-256署名です。

ファームウェアイメージ全体のSHA-256ハッシュを表すbase-16エンコードされた文字列です。

UpdateComponentSegment応答

ファームウェアイメージ全体を受信したら、ガジェットはコマンドIDに94を指定し、ペイロードなしのUpdateComponentSegmentコマンドで応答する必要があります。

ApplyFirmwareコマンド(コマンドID 95)

OTAアップデート中、EchoデバイスはガジェットにApplyFirmwareメッセージを送信し、ガジェットに新しいファームウェアを使うよう指示します。このパケットの例については、Bluetooth Low Energyハンドシェイクのサンプルコードを参照してください。

message ApplyFirmware {
    FirmwareInformation firmware_information = 1;
    bool restart_required = 2;
}
message FirmwareInformation {
    uint32 version = 1;
    string name = 2;
    repeated FirmwareComponent components = 3; 
    string locale = 4; 
    string version_name = 5; 
}

message FirmwareComponent {
    uint32 version = 1;
    string name = 2;
    uint32 size = 3; 
    string signature = 4; 
}
フィールド名 説明 必須

firmware_information

新しいファームウェアバージョンや名前などの情報を含むメッセージです。

FirmwareInformationメッセージ1件が入ります。

restart_required

予約済みです。

この値は無視してください。

FirmwareInformation.version

このガジェットにインストールされているファームウェアのバージョンです。

新しいファームウェアバージョンを表すuint32です。例: 12345

FirmwareInformation.name

Alexaクラウドにアップロードされたファームウェアイメージのバージョンに対応するバージョン文字列です。

バージョン文字列が入ります。例: 1.0.0

FirmwareInformation.components

ファームウェアバージョンやコンポーネント名などの情報を含むメッセージです。

FirmwareComponentメッセージ1件が入ります。

FirmwareInformation.locale

言語と国を含む文字列です。

nullまたは空白を指定できます。

FirmwareInformation.version_name

バージョン名です。

現時点では、FirmwareInformation.nameと同じです。

FirmwareComponent.version

ファームウェアのバージョンです。

現時点では、FirmwareInformation.versionと同じです。

FirmwareComponent.name

コンポーネント名です。

文字列です。

FirmwareComponent.size

ファームウェアイメージのサイズ(バイト)です。

ファームウェアイメージサイズを含むuint32です。例: 552960(540 KB)

FirmwareComponent.signature

予約済みです。

この値は無視してください。

ApplyFirmware応答

ApplyFirmwareコマンドを受信した直後、ガジェットはコマンドIDに95を指定し、ペイロードなしのメッセージで応答する必要があります。

Alexaストリームのペイロード

Alexaストリームのペイロード形式については、Alexa Gadgetのプロトコルバッファー形式を参照してください。

ACKパケットの詳細

トランザクションの最終パケットのヘッダーにACKフラグ(オフセット14)がセットされている場合、ガジェットはACKパケットで応答する必要があります。トランザクションの最終パケットかどうかは、パケットのトランザクションの種類(オフセット12)で判断できます。複数パケットの場合は10、単一パケットの場合は00です。

ACKパケットの全体的なパケット構造はほかのパケットと同じですが、フィールドの値には次のような制限があります。

オフセット(ビット) 長さ(ビット) 説明

0

4

確認をリクエストされたパケットのストリームIDです。

以下のいずれかになります。
0000: 制御ストリーム
0110: Alexaストリーム
0010: OTAストリーム

4 4

確認をリクエストされたパケットのトランザクションIDです。

関連するトランザクションIDです。
8 4 シーケンス番号です。 任意の値を指定できます。
12 2

トランザクションの種類です。

11(制御パケット)

14 1

このパケットがACK、NACKのどちらであるかを示します。

1: ACK
0: NACK

15 1

パケット長を拡張するかどうかを示します。

0

16 8

予約済みです。

0x00

24 8

ACKパケット長(バイト)です。

0x02

32 8

予約済みです。

0x01

40 8

結果コードです。ACK、NACKのどちらになるかに応じて異なります。

SUCCESS: ACK
UNSUPPORTED:NACK

結果コード

一部のメッセージではペイロードに結果コードが含まれます。結果コードはほとんどの場合応答メッセージで使用されます。特に明記されない限り、ガジェットとEchoデバイスでは、「成功」か「成功でない」結果のみを区別します。通常、具体的なエラーメッセージに機能的な違いはありませんが、結果コードはデバッグに役立つ場合があります。

一部のメッセージでは、「成功」以外のすべての結果コードが切断の理由となります。これらのメッセージに成功応答がなければ、ガジェットのコア機能が保証できないからです。以下のメッセージがエラー応答を受け取った場合、接続は切断されます。

  • GetDeviceInformation
  • GetDeviceFeatures

次の表は、メッセージへの応答に使用可能なすべての結果コードの一覧です。

エラー 16進数の値 説明

SUCCESS

0x00

メッセージは有効で、正常に処理されました(該当する場合)。

UNKNOWN

0x01

メッセージは有効でしたが、結果は失敗またはエラーになりました。

UNSUPPORTED

0x03

受信側がサポートしていないコマンドやほかのフィールドが含まれていたため、メッセージは無効です。これは、受信側がサポートしていないすべてのコマンドで使用されます。また、受信側の状態により、メッセージを処理できなかった場合にも使用されます。たとえば、Echoデバイスがインターネットに接続されていない場合、EchoデバイスはエラーコードUNSUPPORTEDstop_speechメッセージを送信できます。

パケットシーケンスの例

以下の図は、MTUや総トランザクション長の異なるAlexa.Discovery.Discoverディレクティブのパケットシーケンスの例です。ペイロード長の拡張を使用した例も1つ紹介しています。

MTUが小さい場合の例

次の例では、MTUが23バイト、総トランザクション長が35バイトです。

Alexa Gadgets Toolkitのパケットシーケンス

MTUが大きい場合の例

次の例では、MTUが247バイト、総トランザクション長が490バイトです。

Alexa Gadgets Toolkitのパケットシーケンス

パケット長を拡張した場合の例

次の例では、MTUが247バイト、総トランザクション長が490バイトで、最初のパケットでペイロードが16ビットであることを示すペイロード長の拡張を使用しています。

Alexa Gadgets Toolkitのパケットシーケンス