Data Protocol

Note the following terminology used in this section:

  • packet: GATT-level byte data including packet headers

  • message: Payload data accumulated from one or more packets (not including packet headers)

This section will describe the data protocol used to send and receive BLE messages. The general procedure to parse a message is to:

  1. Accumulate and depacketize BLE packets to extract the message payload

  2. Decipher the message’s ID and payload type

  3. Depending on the payload type, use the per-message documentation (identified by the message’s ID) to parse the message

Note

All byte ordering is in Big Endian unless otherwise noted.

Packetization

The BLE protocol (<= v4.2) limits packet size to 20 bytes per packet. To accommodate this limitation, GoPro cameras use start and continuation packets to packetize larger payloads. If a message is less than 20 bytes, it can be sent with a single packet containing the start packet header. Otherwise, it must be split into multiple packets with the first packet containing a start packet header and subsequent packets containing continuation packet headers.

Packet Headers

Message sending and receiving is accomplished by prepending General (5-bit), Extended (13-bit), Extended (16-bit), or Continuation headers onto each packet depending on the message size and state.

Note

For byte-level examples of the below packet types, see the tutorials

General (5-bit) Packets

Messages that are 20 bytes or fewer can be sent or received using the following format:

Byte 0
7 6 5 4 3 2 1 0
Start (0) General (00) 5-bit Message Length

Extended (13-bit) Packets

Messages that are 8191 bytes or fewer can be sent or received using the following format:

Byte 0 Byte 1
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Start (0) 13-bit Extended (01) 13-bit Message Length

Tip

Always use Extended (13-bit) packet headers when sending messages to avoid having to work with multiple packet header formats.

Extended (16-bit) Packets

If a message is 8192 bytes or longer, the camera will respond using the format below.

Byte 0 Byte 1 Byte 2
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Start (0) 16-bit Extended (10) Reserved 16-bit Message Length

Warning

This format can not be used for sending messages to the camera. It is only used to receive messages.

Continuation Packets

When sending or receiving a message that is longer than 20 bytes, the message must be split into N packets with packet 1 containing a start packet header and packets 2..N containing a continuation packet header.

Note

Counters start at 0x0 and reset after 0xF.

Byte 0
7 6 5 4 3 2 1 0
Continuation (1) Reserved 4-bit Counter

Decipher Message Payload Type

Once the packets have been accumulated and the payload has been extracted, it is necessary to decipher the message type in order to determine whether it is TLV or Protobuf and then parse it appropriately.

Below is pseudocode describing how to do this:

Camera sends response message from UUID U (string) with payload P (array of bytes)
// Is it a Protobuf response?
for each row in the Protobuf IDs table {
    F (int) = Feature ID
    A (array of int) = Action IDs
    if P[0] == F and P[1] in A {
        P is a Protobuf Message
        Match Feature ID P[0] and Action ID P[1] to a Protobuf message in the Protobuf IDs table
        Use matched Protobuf message to parse byte payload into useful data structure
        Exit
    }
}
// Nope. It is a TLV response
if U == GP-0072 (Command) {
    Parse message payload using Command Table with Command scheme
}
else if U == GP-0074 (Settings) {
    Parse using Setting ID mapping with Command scheme
}
else if U == GP-0076 (Query) {
    Parse message payload using Query Table with Query scheme
}

Alternatively this is described in flowchart form here:

../_images/plantuml_ble_tlv_vs_protobuf.png

Message Payload

Once the payload has been extracted and had its type deciphered, it can then be parsed depending on its type. The Open GoPro protocol uses two different top-level message payload formats:

Note

The byte table examples in this section do not contain the Packet Headers; they only consider the payload.

Type Length Value

There are two different request / response Type-Length-Value (TLV) schemes as described in the following sections.

Commands

Commands are messages sent / received on either:

They are summarized in the commands table and individually documented throughout the relevant feature section.

Command Request

Below is the top level message format for command requests:

Type (Command / Setting ID) Optional Parameters
1 Byte Array of length-value pairs

where each element of the parameter array is:

Length Value
1 Byte Length Bytes

The individual command documentation specified by the message’s Command ID will define the length and value options for each of its parameters.

Command Response

Below is the top level message format for command responses:

Type (Command / Setting ID) Command Status Optional Response
1 Byte 1 Byte Variable Length

where the possible Command Statuses are:

Command Status Description
0 Success
1 Error
2 Invalid Parameter
3-255 Reserved

The individual command documentation specified by the message’s Command ID will define the response.

Tip

For byte-level examples, see the tutorials.

Queries

Queries are messages sent / received on the Query and Query Response characteristics, respectively. They are summarized in the queries table and individually documented in Query.

Query Request

Below is the top level message format for query requests:

Query ID Array of Element IDs
1 Byte Variable

The individual query documentation specified by the message’s Query ID will define the elements that comprise the element ID array.

Query Response

Below is the top level message format for query responses:

Query ID Command Status Query Results
1 Byte 1 Byte Array of id-length-value triplets

where each element of the results array is:

ID Length Value
1 Byte 1 byte Length Bytes

The individual query documentation specified by the message’s Query ID will define the format of the result array.

Tip

For byte-level examples, see the tutorials.

Protobuf

In order to maximize BLE bandwidth, some commands use Google Protobuf (Protocol Buffers). Open GoPro currently uses Protocol Buffers Version 2

Protobuf requests and responses are identified by a Feature ID and an Action ID prepended before their serialized payload. The top level message format for a Protobuf message is as follows:

Feature ID Action ID Serialized Protobuf Message
1 Byte 1 Byte Variable Length

The individual Protobuf object specified by the message’s action / feature id is used to serialize / deserialize the payload.

Backwards Compatibility

It is possible that some Protobuf message fields can be individually deprecated in which case they will be removed from the Message definition in the .proto file. The best solution to handle this is to use the newest .proto files.

Even when using the old .proto files there should be no problem serializing / deserializing. However, ensure to set the ignore_unknown_fields argument to True when relevant for Json-Protobuf conversion functions.