Data Packet for Bluetooth Low Energy


This topic describes the packet format that Echo devices and gadgets use to exchange data over Bluetooth Low Energy (BLE).

For Alexa Gadgets Toolkit issues related to Bluetooth, see Bluetooth on the known issues page.

Concepts

To understand the packets that Echo devices and gadgets exchange over BLE, you need to be familiar with the concepts of streams and transactions.

Streams

Streams provide a way to separate packets into different types. Gadgets must support the following streams:

  • Control stream – This stream enables Echo devices and gadgets to communicate. The payloads for these packets manage the gadget configuration, exchange device information during the initial handshake, and so on.
  • Alexa stream – Echo devices and gadgets use this stream to send directives and events for all Alexa Gadgets Toolkit interfaces.
  • Over-the-air (OTA) stream – Echo devices and gadgets use this stream to update the gadget's firmware in the OTA update process.

At any given time, there is only one control stream, one Alexa stream, and one OTA stream (if applicable). Each packet belongs to one of these streams, which is specified in the stream ID field of the packet's header. The stream ID enables the receiver (gadget or Echo device) to interpret the packet's payload.

Transactions

Transactions are logical chunks of data that can be acted upon. A transaction can be a single packet of data or multiple packets of data, depending on the MTU size. The transaction type, which is at offset 12 in the header of each packet, specifies whether the packet is at the beginning, end, or middle of the transaction. The combination of transaction ID and stream ID uniquely identifies a message.

Packet format

Packets are binary and each field is stored as big endian. Each packet consists of a header and a payload. The header contains a stream ID, transaction ID, and so on. The format of the payload depends on the stream type (control stream or Alexa stream).

Acknowledgment (ACK) packets

If the Echo device requests it, the gadget must send the Echo device an ACK packet in response to the last packet of the transaction. ACK packets have the same overall packet structure as other packets, but certain fields must be set to the values specified in ACK packet details.

To determine if the transaction requires an ACK, the gadget should check the ACK flag (offset 14) in the header of the last packet of the transaction. Note that you can identify the last packet of the transaction by the packet's transaction type (offset 12): in a multiple-packet transaction, the last packet's transaction type will be 10; in single-packet transactions, the packet's transaction type will be 00.

The ACK packet must use the same stream ID and transaction ID of the transaction being acknowledged. Both the control stream and the Alexa stream support ACK packets. Currently, the Echo device can request that the gadget send an ACK packet, but not vice versa.

Each packet has a header. The size of the packet's header depends on two factors:

  • Location of the packet within the transaction – The header of the first packet of the transaction contains an additional 24 bits (a reserved field and a transaction length field).
  • Payload length field extension – The payload length field in the header can either be unextended (8 bits) or extended (16 bits). The one-bit length extender field indicates whether the payload length is extended.

The following are visual representations of headers with unextended and extended payload length fields. As indicated, some fields are only present in the first packet of the transaction. For examples of Alexa.Discovery.Discover directive headers for different MTU and total transaction length sizes, see Example packet sequences.

Header with unextended payload length field

Alexa Gadgets Toolkit packet header with unextended payload length

Header with extended payload length field

Alexa Gadgets Toolkit packet header with extended payload length

The fields in the header are as follows:

Offset (bits) Length (bits) Description Value
0 4

The stream ID.

0000: Control stream
0110: Alexa stream
0010: OTA stream

4 4

The transaction ID.

A number that is unique per transaction for a stream ID at any given point of time. Packets that belong to different streams can have the same transaction ID at the same time.

8 4 Sequence number. Since this is four bits long, it supports in-place sequencing of up to 16 packets at a given point in time.

Sequence numbers can roll over. When packets are out of order (and therefore sequence numbers are out of order), you should drop the transaction. For example, 0 after 16 is in order, but 10 after 16 is out of order.

A number that is incremented per transaction.

12 2

Transaction type, which indicates where the packet is within the transaction. The transaction type and protocol of a single transaction are defined by the first packet of the transaction.

00: First packet of a transaction, or the only packet in a single-packet transaction.
01: Continuation packet of a transaction (that is, any but the first and last packet).
10: Last packet of a transaction.
11: Control packet. Currently, the only type of control packet is the ACK packet.

14 1

Acknowledgement (ACK) flag.

0: The gadget does not need to send an ACK packet in response to the last packet of the transaction unless another packet in the transaction has this bit set to 1.
1: The gadget must send an ACK packet in response to the last packet of the transaction.

15 1

Length extender.

This bit indicates the length of the payload field. Otherwise, it is 8 bits long. The length extender field is dynamic based on how much data is filled in that specific MTU. This means that a specific packet on a transaction might have a length extender set to 1, and another packet might have it set to zero.

0: The packet's payload is 8 bits.
1: The packet's payload is 16 bits.

16 8 Reserved. This is only present in the first packet of the transaction.

0: Currently the only possible value.

24 16 Total transaction length. This is only present in the first packet of the transaction. Single-packet transactions should include this field. Transaction length, in bytes.
40 or 16 8 or 16

Payload length. Every packet has its own payload length.

The offset and length of this field depend on the two factors described previously:

Location of the packet within the transaction – In the first packet of the transaction, the offset is bit 40. In subsequent packets of the transaction, the offset is bit 16.

Payload length field extension – This depends on the value of the length extender bit earlier in the header. If that bit is not set, the payload length field is 8 bits. If that bit is set, the payload length field is 16 bits.

Payload length, in bytes.

Payload types

Each payload is in protocol buffer format using proto3 syntax. The payload can be one of two types, depending on the stream type:

Control stream payload

The control stream enables an Echo device and a gadget to communicate. Each control stream message consists of an envelope, which contains a payload.

Envelope

The control stream payload's envelope, in protocol buffer format, is as follows:

message ControlEnvelope {
    Command command = 1;
 
    oneof payload {
        // Response
        Response response = 9;
 
        // Messages
        // ...
    }
}

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

Response

When the gadget receives a supported control stream message from the Echo device, the gadget must send a control stream message in response. The response message can have a payload, depending on the command associated with that message. If a gadget receives a control stream message that it does not understand, it should respond with a result code of UNSUPPORTED.

message Response {
    ErrorCode error_code = 1;
 
    oneof payload {
        // Optional data
    }
}

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

Specific control stream payloads

Control stream packets that the gadget and the Echo device exchange can have one of the following payloads:

Message Command ID Who sends it When it's used

DeviceInformation command

20

Echo device

Handshake

DeviceInformation response

20

Gadget

Handshake

DeviceFeatures command

28

Echo device

Handshake

DeviceFeatures response

28

Gadget

Handshake

UpdateComponentSegment command

94

Echo device

OTA

UpdateComponentSegment response

94

Gadget

OTA

ApplyFirmware command

95

Echo device

OTA

ApplyFirmware response

95

Gadget

OTA

DeviceInformation command (Command ID 20)

To query the gadget for its device information during the handshake, the Echo device sends the gadget a control envelope with the command set to 20 (GET_DEVICE_INFORMATION). For an example of this packet, see the sample code described in Bluetooth Low Energy Handshake Sample Code.

DeviceInformation response

When the Echo device queries the gadget for its device information during the handshake, the gadget must respond with a packet that contains a control envelope with a payload that contains device information.

For an example of this packet, see the sample code described in Bluetooth Low Energy Handshake Sample Code.

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

enum Transport {
   BLUETOOTH_LOW_ENERGY = 0;
}
Field Name Description Value Required

serial_number

Unique device serial number (DSN) of the gadget.

The same string as the endpointId in the Discovery response. For more details, see Gadget ID Requirements for Alexa Gadgets.

Yes

name

A user-friendly name of the gadget. This name can be changed by a user.

The same string as the friendlyName in the Discovery response.

Yes

supported_transports

A collection of transports that the gadget supports. This field enables the Echo device to choose the best transport to communicate with the gadget over.

A list of supported transports. This value is currently [BLUETOOTH_LOW_ENERGY].

Yes

device_type

Unique device type assigned by Amazon.

The same string as amazonDeviceType in the Discovery response.

Yes
DeviceFeatures command (Command ID 28)

To query the gadget for its device features during the handshake, the Echo device sends the gadget a control envelope with the command set to 28 (GET_DEVICE_FEATURES). For an example of this packet, see the sample code described in Bluetooth Low Energy Handshake Sample Code.

DeviceFeatures response

When the Echo device queries the gadget for its device features, the gadget must respond with a packet that specifies the features that the gadget supports. For an example of this packet, see the sample code described in Bluetooth Low Energy Handshake Sample Code.

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

Field Name Description Value Required

features

The features that the gadget supports.

A uint64 with bits defined as follows:

Offset 0: Set to 1 if the gadget supports the Alexa Gadgets Toolkit feature set.

Offset 1: Set to 1 if the gadget supports OTA updates.

Offset 2: Set to 0.

Offset 3: Set to 0.

Offset 4: Set to 1.

Offset 5-63: Set to 0.

Yes

device_attributes

Reserved.

A uint64 with a value of 0.

Yes
UpdateComponentSegment command (Command ID 94)

If the Alexa service determines that the gadget needs an OTA update, the Echo device sends the gadget an UpdateComponentSegment message. For an example of this packet, see the sample code described in Bluetooth Low Energy Handshake Sample Code.

message UpdateComponentSegment {
    string component_name = 1; 
    uint32 component_offset = 2; 
    uint32 segment_size = 3; 
    string segment_signature = 4; 
}
Field Name Description Value Required

component_name

The component name.

A string.

Yes

component_offset

The offset of the component, in bytes.

A uint64 with a value of 0.

Yes

segment_size

The size of the firmware image, in bytes.

A uint32 with a value of the number of bytes in the firmware image.

Yes

segment_signature

The SHA-256 signature of the firmware image.

A base-16-encoded string that represents the SHA-256 hash of the entire firmware image.

Yes
UpdateComponentSegment response

After the gadget receives the entire firmware image, it must respond to the UpdateComponentSegment command with a message that specifies command ID 94 but does not have a payload.

ApplyFirmware command (Command ID 95)

During an OTA update, the Echo device sends the gadget an ApplyFirmware message to instruct the gadget to use the new firmware. For an example of this packet, see the sample code described in Bluetooth Low Energy Handshake Sample Code.

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; 
}
Field Name Description Value Required

firmware_information

Message that contains information such as the new firmware version, name, and so on.

One FirmwareInformation message.

Yes

restart_required

Reserved.

Ignore this value.

Yes

FirmwareInformation.version

The version of the firmware that is being installed on the gadget.

A uint32 that represents the new firmware version. Example: 12345.

Yes

FirmwareInformation.name

The version string that corresponds to the version of the firmware image that was uploaded to the Alexa cloud.

A version string. Example: 1.0.0.

Yes

FirmwareInformation.components

Message that contains information such as the firmware version, component name, and so on.

One FirmwareComponent message.

Yes

FirmwareInformation.locale

String that contains the language and country.

May be null or blank.

Yes

FirmwareInformation.version_name

The version name.

Currently the same as FirmwareInformation.name.

Yes

FirmwareComponent.version

The firmware version.

Currently the same as FirmwareInformation.version.

Yes

FirmwareComponent.name

The component name.

A string.

Yes

FirmwareComponent.size

The size of the firmware image, in bytes.

A uint32 that contains the firmware image size. Example: 552960 (for 540 KB).

Yes

FirmwareComponent.signature

Reserved.

Ignore this value.

Yes
ApplyFirmware response

Immediately after the gadget receives the ApplyFirmware command, it must respond with a message that specifies command ID 95 but does not have a payload.

Alexa stream payload

For information on the Alexa stream payload format, see Protocol Buffer Format for Alexa Gadgets.

ACK packet details

If the ACK flag (offset 14) is set in the header of the last packet of the transaction, the gadget must respond with an ACK packet. Note that you can identify the last packet of the transaction by the packet's transaction type (offset 12): in a multiple-packet transaction, the last packet's transaction type will be 10; in single-packet transactions, the packet's transaction type will be 00.

The ACK packet has the same overall packet structure as other packets, but its field values are restricted to certain values as follows:

Offset (bits) Length (bits) Description Value

0

4

The stream ID of the packet that requested the acknowledgement.

One of the following:
0000: Control stream
0110: Alexa stream
0010: OTA stream

4 4

The transaction ID of the packet that requested the acknowledgement.

The associated transaction ID.
8 4 Sequence number. This can be any value.
12 2

Transaction type.

11 (Control packet)

14 1

Whether this packet is an ACK or a NACK.

1: ACK
0: NACK

15 1

Length extender.

0

16 8

Reserved.

0x00

24 8

Length of the ACK packet, in bytes.

0x02

32 8

Reserved.

0x01

40 8

A result code, which depends on whether this is an ACK or a NACK.

SUCCESS for ACK
UNSUPPORTED for NACK

Result codes

Some messages contain a result code in their payload. Result codes are mostly used in response messages. Unless otherwise noted, the gadget and the Echo device are only expected to differentiate between two types of result codes: success and not success. While the specific error message does not typically make a functional difference, result codes can help with debugging.

For some messages, any result code but success is a reason to disconnect because without a success response to these messages, the core functionality of the gadget cannot be guaranteed. If the following messages receive an error response, a disconnect will occur:

  • GetDeviceInformation
  • GetDeviceFeatures

The following table lists all of the result codes that can be used in response to a message.

Error Hex value Description

SUCCESS

0x00

The message was valid and acted on (if applicable) successfully.

UNKNOWN

0x01

The message was valid but resulted in a failure or error.

UNSUPPORTED

0x03

The message was invalid because it contained a command or other field that was not supported by the receiver. This should be used for any command that the receiver doesn't support. It should also be used for cases where the message could not be acted on because of the state of the receiver. For example, the Echo device might send a stop_speech message with error code UNSUPPORTED if the Echo device isn't connected to the internet.

Example packet sequences

The following figures show example packet sequences for an Alexa.Discovery.Discover directive with different MTU and total transaction length sizes. One example uses the payload length extender also.

Example with small MTU

In the following example, the MTU is 23 bytes and the total transaction length is 35 bytes.

Alexa Gadgets Toolkit packet sequence

Example with larger MTU

In the following example, the MTU is 247 bytes and the total transaction length is 490 bytes.

Alexa Gadgets Toolkit packet sequence

Example with length extender

In the following example, the MTU is 247 bytes, the total transaction length is 490 bytes, and the first packet uses the length extender to signify that the payload is 16 bits.

Alexa Gadgets Toolkit packet sequence


Was this page helpful?

Last updated: Feb 14, 2022