Skip to content

Garmin Protocol

There are (at least) two big families of garmin protocol: both are using BLE. The first protocol uses different characteristics to transfer different type of information and appears to be in use on older wearables: the aforementioned contribution made Gadgetbridge support this version of the protocol.

A newer protocol uses the same characteristics for every information transfer, by encapsulating this in "threads" (or handles, or conversations) whose identifiers are prepended to each message exchange. This version of the protocol is currently unsupported.

A third version of the protocol was also reported (see issue #3063) that apparently adds some kind of sequence between the thread/handle/conversation ID and the actual payload, while using the same characteristic.

The difference between the first protocol and the rest can be detected early by the presence of the specific characteristic used in newer protocols. The second and the third protocol might probably be chosen according to some early handshake values and the way some identifiers are chosen by the watch, so it should be possible to support all three generations of the protocols with relatively little effort.

Protocol description

The following is a description of the protocol used by the Garmin Forerunner 245 (firmware version 13.00) and the Garmin Connect Android application version 4.66. This can be used as a basis for reimplementation, possibly in addition to package captures, application logs, and experiments involving unspecified input sequences.

Bluetooth LE service

The table below was retrieved using bettercap. The protocol described in this document is termed Multi-Link / ML and is exposed using the service 6A4E2800-667B-11E3-949A-0800200C9A66. It comprised an unknown characteristic 2803 as well as three pairs of characteristics, each implementing a read and a write queue. Writing to any of the three characteristics 2820, 2821, 2822 will elicit a reply in the respective readable characteristic 2810, 2811, or 2812. Writing to any of the latter will produce a reply on the same characteristic.

Handles Service > Characteristics Properties Data
0001 -> 0009 Generic Access (1800)
0003 - Device Name (2a00) READ Forerunner 245
0005 - Appearance (2a01) READ Watch: Sports Watch
0007 - Peripheral Preferred Connection Parameters (2a04) READ Connection Interval: 24 -> 36
Slave Latency: 0
Connection Supervision Timeout Multiplier: 400
0009 - 2aa6 READ 00
000a -> 000d Generic Attribute (1801)
000c - Service Changed (2a05) INDICATE
000e -> 0013 6a4e8022667b11e3949a0800200c9a66
0010 - 6a4e4c80667b11e3949a0800200c9a66 WRITE
0012 - 6a4ecd28667b11e3949a0800200c9a66 READ, NOTIFY
0014 -> 0025 6a4e2800667b11e3949a0800200c9a66
0016 - 6a4e2803667b11e3949a0800200c9a66 READ, WRITE 00Ã’5y
0018 - 6a4e2810667b11e3949a0800200c9a66 READ, WRITE, NOTIFY 0800020a058813©130103Ëm00
001b - 6a4e2820667b11e3949a0800200c9a66 WRITE
001d - 6a4e2811667b11e3949a0800200c9a66 READ, WRITE, NOTIFY
0020 - 6a4e2821667b11e3949a0800200c9a66 WRITE
0022 - 6a4e2812667b11e3949a0800200c9a66 READ, WRITE, NOTIFY
0025 - 6a4e2822667b11e3949a0800200c9a66 WRITE
0026 -> 0029 Heart Rate (180d)
0028 - Heart Rate Measurement (2a37) NOTIFY
002a -> 002f Running Speed and Cadence (1814)
002c - RSC Feature (2a54) READ 0000
002e - RSC Measurement (2a53) NOTIFY

The Multi-Link protocol (MultiLink, ML) acts as a multiplexer of services. Newer watches support a variant called Multi-Link reliable (MLR), which is not covered by this document. Services inlude GFDI (Garmin Fit Data Interface ? -- just guessing) as implemented by older watches, e.g. the Vivomove HR, registration (query device information), and various real-time information that were previously handled using dedicated characteristics. They are identified by a short value, see [services]. Furthermore, a 8-byte value client_uuid is used by the application. The Garmin Connect application is configured to use 0x01. ML consists of two components: handle management (service registration, closing handles) and transportation via chunking, encoding, and prefixing of a handle.

Handle management

Handle management consists of messages with minimum length 2 starting with 0x00. No other messages start with 0x00, as they are prefixed using a non-zero handle byte. The second byte indicates the message type, which in turn determines the message length. The byte encoding is little-endian.

Byte Description
0x00 Register ML/MLR service request
0x01 Register ML/MLR service response
0x02 Close handle request
0x03 Close handle response
0x04 Unknown handle response
0x05 Close all handles request
0x06 Close all handles response
0x07 Unknown request
0x08 Unknown response
0xff Protocol error response

General format

00 ?? ???????????????? ???? ...
   - message type byte, see above
      - client_uuid, 8 bytes
                       - service, 2 bytes
                            - 0-4 message-dependent bytes
Responses contain the client_uuid and service values from the respective request.

Register ML/MLR service request

Before using any service, it must be registered to a handle.

0000 ???????????????? ???? ??
     - client_uuid, 8 byte
                      - service, 2 byte
                           - 00: request not reliable (ML)
                           - 02: request reliable (MLR)

Example:
0000 0100000000000000 0400 00
client_uuid = 0x01
service = 0x04 (REGISTRATION)
request_reliable = 0x00 (use ML instead of MLR)

Register ML/MLR service response

Registering an already connected service will return SUCCESS using the same handle if the client_uuid is the same. Doing the same using a different client_uuid will result in an ALREADY_IN_USE reply, indcating a characteristic that might allow registering said service instead.

0001 ???????????????? 0400 00 ...
     - client_uuid, 8 byte
                      - service, 2 byte
                           - status
                           - 0x00: SUCCESS
                           - 0x01: INVALID_SERVICE_ID (or request message too short)
                           - 0x02: PENDING_AUTH
                           - 0x03: ALREADY_IN_USE
                           - 0x04: REJECTED

Known messages formats:
0x00 ?? [?? [??]]
     - handle
         - reliable (byte)
           - 0x00: ML (default)
           - > 0x00: MLR (not covered in this spec)
             - REGISTRATION as ML service (byte)
               - 0x00: legacy characteristic
               - & 0x01: use ML service
0x00 ?? 00 01 (registered as unreliable)
     - handle (byte)
0x00 ?? 01 00 (registered as reliable)
     - handle (byte)
0x01 (invalid service id)
0x03 ?? ?? (service registerd by another client_uuid)
     - free char uuid

Examples:
0001 0100000000000000 0400 00 01 00 01
- SUCCESS, handle=0x01, reliable=False, mlService=True

0001 0100000000000000 0600 03 12 28
- ALREADY_IN_USE by 6a4e2812-667b-11e3-949a-0800200c9a66

0001 0100000000000000 0400 00 09 00
- SUCCESS, reliable=False, mlService=False (use dedicated registration characteristic)
0001 0100000000000000 0400 00 2e 00 01
- SUCCESS, handle=0x2e, reliable=False, mlService=True
0001 0100000000000000 0400 00 68 00 01
- SUCCESS, handle=0x68, reliable=False, mlService=True

0000 0100000000000001 0400 00 04 01 01
- SUCCESS, handle=0x04, reliable=True, mlService=True

0001 0100000000400000 0400 03 10 28
status = 0x03 ALREADY_IN_USE
occupied by char 6a4e2810-667b-11e3-949a-0800200c9a66

0001 0100000000500000 0300 01
status = 0x01, INVALID_SERVICE_ID (HEALTH_SDK not supported or request message invalid)

0001 0100000000000000 0100 00 86 01 00
status = 0x00, handle=0x86, reliable=True. Last byte does not seem to be relevant.

Close handle request

0002 ???????????????? ???? ??
     - client_uuid
                      - service (short)
                           - handle

Example:
0002 0100000000000000 0600 35
client_uuid = 0x01
service = 6
handle = 0x35

Close handle response

0003 ???????????????? ???? ?? ??
     - client_uuid
                      - service (short)
                           - handle (byte)
                              - status
                              - 00: SUCCESS
                              - 01: INVALID_HANDLE
                              - 02: NO_CONNECTION

Example:
0003 0100000000000000 0600 35 00
client_uuid: 0x01
service: 6
handle: 0x35
status: SUCCESS

0003 0100000000000000 0600 35 02

Unknown handle response

This message can be expected when the watch receives a message with an unregistered handle. I haven't observed the structure.

0004 0000000000000000 0000 ??
                           - handle (byte)

Example:
0004 0000000000000000 0000 12
handle: 0x12

Close all handles request

0005 ???????????????? ????
     - client_uuid
                      - flags? unused
Example:
0005 0100000000000000 0000
client_uuid = 0x01

Close all handles response

0006 ???????????????? ???? ??
                      - flags from request
                           - status, unused

0006 0100000000000000 0000 01
client_uuid = 0x01
status = 0x01, unused

Unknown request

0007 ???????????????? ????
     - client_id
                      - flags

Unknown response

0008 ???????????????? ???? 01
     - client_id
                      - flags from request

Invalid request response

Example
00ff 0100000000000000 1234 10

Services

ID Service
1 GFDI
2 NFC
3 HEALTH_SDK
4 REGISTRATION
5 CONNEXT
6 REAL_TIME_HR
7 REAL_TIME_STEPS
8 REAL_TIME_CALORIES
9 REAL_TIME_FLOORS
10 REAL_TIME_INTENSITY
11 REAL_TIME_DUMMY
12 REAL_TIME_HRV
13 REAL_TIME_STRESS
14 AUTH_STATUS
15 ECHO
16 REAL_TIME_ACCELEROMETER
17 REAL_TIME_SPAM
18 REAL_TIME_BMX_RAW
19 REAL_TIME_SPO2
20 REAL_TIME_BODY_BATTERY
21 REAL_TIME_RESPIRATION
22 KEEP_ALIVE
26 REAL_TIME_ACTIVE_TIME

For example, the Garmin Forerunner 245 (firmware version 13.00) supports services 1, 4, 6, 7, 8, 10, 12, 13, 16, 19, 20, 21, 22, which correspond to GFDI, REGISTRATION, REAL_TIME_{HR,STEPS,CALORIES,INTENSITY,HRV,STRESS,ACCELEROMETER,SPO2,BODY_BATTERY,RESPIRATION}, KEEP_ALIVE.

Registration service

The registration service exposes information on the supported services (e.g. GFDI, REAL_TIME_*), version information, and other yet to be idenfied information.

Requests are performed using by sending a single byte via to the registration characteristic or two bytes (ML handle plus single byte) to the REGISTRATION service.

Byte Name Description
0x00 SUPPORTED_PROTOCOLS List supported protocols, aka supportedServiceIds
0x01 ADVERTISING_DATA Referenced as advertisingServiceData, e.g. 0, 19, 64, read byte-wise. Unknown purpose
0x02 MULTI_LINK_VERSION Referenced as MultiLinkVersion, e.g. 2.2.1
0x03 PRODUCT_NUMBER Product number, firmware version, unit id
0x04 IDENTITY_ADDRESS Haven't seen this one being used yet

The unit id is used when communicating to Garmin's servers and probably identifies the device uniquely.

Examples, assuming handle 0x32:

> 3200 # request available multi-link service
< 3200 d23579 # available multilink services [1, 4, 6, 7, 8, 10, 12, 13, 16, 19, 20, 21, 22]
# 0b 1101 0010  0011 0101  0111 1001
     00 0   0     11  1 0   222 1  1
     76 4   1     32  0 8   210 9  6
> 3201
< 3201 00 13 40 # advertisingServiceData=[0, 19, 64]
> 3202
< 3202 01 02 02 # MultiLinkVersion(major=2, minor=2, micro=1)
> 3203
< 3203 040c 1405 deadbeef # productNumber=3076 firmwareVersion=1300 unitId=4022250974
> 3204
< 3204 ???????????????????????????????? # identityAddress, 16 bytes

GFDI

GFDI has been described by [1]. Messages are COBS-encoded by splitting them into chunks (split at each zero byte, remove zero byte prefix using resulting chunk length plus one. The maximum chunk length is 254. Chunks of length 254 are encoded by adding a 0xff byte. Chunks with size greater than 253 increase the encoded message length by at least 1.

Request messages consist of a two-byte length field, a two-byte message type field that can include a 5-bit sequence number, a message-dependent part, as well as a two-byte CRC value (Crc16, e.g. crc-16 from python-crcmod).

???? ???? ............ ????
- length, including this length field and the CRC
     - message type, possibly a sequence number
          - message type-specific contents
                       - CRC

If the fourth byte has its most-significant bit set, i.e. req[3] & 0x80, then this byte's five least significant bits encode a sequence number req[3] & 0x1f and the encoded message type is encoded using the third byte, i.e. 5000 + req[2]. This scheme allows correlating GFDI requests and responses. The sequence number is usually increased by one with every request sent and wraps around to 0 after reaching 31.

Examples:

0900 08 98 280110 d7f5
- length: 9 bytes
     - message type: 8 + 5000 = 5008 (Set File Flags request)
        - flags
        - 0x80: use single-byte encoding for message type
        - 0x18: sequence number
           - data
                  - CRC

1e00 b413 .... a6ec
- length: 30 bytes
     - message type: 5044
          - data
               - CRC

1e00 2c 85 .... a6dd
- length: 30 bytes
     - message type: 5044
        - flags
        - 0x80: use single-byte encoding for message type
        - 0x05: sequence number

Unlike GFDI requests, GFDI responses are not acknowledged. Their message type is 5000. The encoding of this message type depends on the corresponding request's scheme: if the req[3] & 0x80 bit was set, theresponse's message type will be encoded in the third byte and the fourth byte will be contain the sequence number from the corresponding request. Otherwise both bytes will be used to encode the message type 5000. The corresponding request's message type is always encoded using two bytes, followed by a status byte.

???? 1388 ???? ?? ......... ????
- length
     - message type: 5000 (response)
          - original message type in two-byte format
               - status
               - 0x00: ACK
               - 0x01: NAK
               - 0x02: UNKNOWN_OR_NOT_SUPPORTED
               - 0x03: COBS_DECODER_ERROR
               - 0x04: CRC_ERROR
               - 0x05: LENGTH_ERROR

???? 00?? ???? ?? ......... ????
- length
     - message type: 5000 minus 5000 = 0
       - 0x80 flag set plus sequence number of the original request
          - original message type in two-byte format
               - status
               - 0x00: ACK
               - 0x01: NAK
               - 0x02: UNKNOWN_OR_NOT_SUPPORTED
               - 0x03: COBS_DECODER_ERROR
               - 0x04: CRC_ERROR
               - 0x05: LENGTH_ERROR

Example:

0d00 0096 9013 00 00c50010 31b1
- length: 13
     - message type: 5000
       - sequence number: 0x16
          - corresponding request's message type: 5008
               - status: ACK
                  - data
                          - crc

ML service transport

ML services use the same characteristic(s) as the ML control protocol. All service-related communication is prefixed by the service's handle byte, as indicated in the /register service response/. The maximum message length is 20.

Handle management

Services are registered to single-byte handles by the ML protocol. Establishing a connection typically looks like this:

  1. Pick characteristic, try registering information service until succeeds
  2. Query services and other information using REGISTRATION protocol
  3. Register GFDI and optionally KEEP_ALIVE
  4. Optionally, unregister REGISTRATION

Relevant GFDI messages

5008 Set File Flags

This request allows archiving files. Confirmation whether this deletes files or changes their file index is missing.

???? 10
- file index, uint16, little endian
     - flags: archive

Examples:

# Request: archive file
c600 10
- file index: 0x00c6
     - flags: archive (0x10)

# Full GFDI Response: only the ACK part seems to be relevant
0d00 0096 9013 00 00 c500 10 31b1
- length
     - message type = 5000 (0 + 5000 due to flags)
       - flags: 0x8: add 5000 to message type
       - 0x16: GFDI message sequence number for referencing
          - response to 5008
               - ACK
                  - Unknown, status?
                     - File index-related. Perhaps the file got a new file index?
                          - flags
                             - crc

# Full GFDI Request: archive file
0900 0898 2801 10 d7f5
       - 0x18: GFDI message sequence number
          - file index: 0x0128
               - flags: archive file
                  - crc

# Full GFDI Response
0d00 0098 9013 00 00 2701 10 119b
       - 0x18: GFDI message sequence number
               - ACK
                  -  Unknown, status?
                     - File index-related. Original file index minus one?
                          - flags: archive file
                             - crc

Added GNCS services

This section describes a subset of previously undocumented GNCS protobuf-related services relevant for the Garmin Forerunner 245.

gdi_data_types

Enums:

GPSFixType = {FORCE_NO_SOLUTION=1, NO_SOLUTION, DEAD_RECKONING, TWO_D, THREE_D, TWO_D_DIFFERENTIAL, THREE_D_DIFFERENTIAL}
Languages = {UNKNOWN=0, AFRIKAANS, ALBANIAN, ARABIC, ARMENIAN, AZERBAIJANI, BASQUE, BELARUSIAN, BENGALI, BOSNIAN, BULGARIAN, CATALAN, CHINESE_SIMPLIFIED, CHINESE_TRADITIONAL_HONG_KONG, CHINESE_TRADITIONAL_TAIWAN, CROATIAN, CZECH, DANISH, DUTCH, ENGLISH_UK, ENGLISH_US, ESPERANTO, ESTONIAN, FAROESE, FILIPINO, FINNISH, FRENCH_CANADA, FRENCH_FRANCE, FRISIAN, GALICIAN, GEORGIAN, GERMAN, GREEK, HEBREW, HINDI, HUNGARIAN, ICELANDIC, INDONESIAN, IRISH, ITALIAN, JAPANESE, KHMER, KOREAN, KURDISH, LATIN, LATVIAN, LITHUANIAN, MACEDONIAN, MALAY, MALAYALAM, NEPALI, NORWEGIAN_BOKMAL, NORWEGIAN_NYNORSK, PASHTO, PERSIAN, POLISH, PORTUGUESE_BRAZIL, PORTUGUESE_PORTUGAL, PUNJABI, ROMANIAN, RUSSIAN, SERBIAN, SLOVAK, SLOVENIAN, SPANISH, SPANISH_SPAIN, SWAHILI, SWEDISH, TAMIL, TELUGU, THAI, TURKISH, UKRAINIAN, VIETNAMESE, WELSH, ENGLISH_AUSTRALIA}
CoordinateSystem = {WGS84=0, GCJ02}
CompassDirection = {NORTH=0, NORTH_NORTHEAST, NORTHEAST, EAST_NORTHEAST, EAST, EAST_SOUTHEAST, SOUTHEAST, SOUTH_SOUTHEAST, SOUTH, SOUTH_SOUTHWEST, SOUTHWEST, WEST_SOUTHWEST, WEST, WEST_NORTHWEST, NORTHWEST, NORTH_NORTHWEST}

ScPoint

Field number Optional Message type Field name Default
1 [ ] sint32 lat
2 [ ] sint32 lon

UUID

Field number Optional Message type Field name Default
1 [ ] fixed64 most_significant
2 [ ] fixed64 least_significant

Locale

Field number Optional Message type Field name Default
1 [ ] uint32 id
2 [ ] uint32 size

DataTransferItem

Field number Optional Message type Field name Default
1 [ ] uint32 id
2 [ ] uint32 size

GDISmart

This section covers previously undocumented extensions of the GDISmart protocol relevant for the Forerunner 245.

Optional fields of the Smart message:

Field number Message type
1 CalendarService
2 ConnectIQHTTPService
7 DataTransferService
49 GNCSService

GNCSService

Field number Optional Message type Field name Default
1 [X] MediaRequest media_request
2 [X] MediaResponse media_response
MediaRequest
Field number Optional Message type Field name Default
1 [X] uint32 notification_uid
2 [X] uint32 index
3 [X] DisplayAttributes attributes
4 repeated MediaType supported_types
MediaResponse

Enums:

Status = {UNKNOWN=0, SUCCESS, INVALID_UID, INVALID_INDEX}
| Field number | Optional | Message type | Field name | Default | | --- | --- | --- | --- | --- | | 1 | [X] | Status | status || | 2 | [X] | uint32 | notification_uid || | 3 | [X] | uint32 | index || | 4 | [X] | MediaType | type || | 5 | [X] | DataTransferItem (from gdi_data_types) | transfer_info ||
CapabilitiesRequest

This message extends CoreService.FeatureCapabilitiesRequest with

Field number Optional Message type Field name Default
12 [X] CapabilitiesRequest gncs

and has

Field number Optional Message type Field name Default
1 [X] uint32 np_version
2 [X] NotificationDisabledReason notification_disabled_reason
CapabilitiesResponse

This message extends CoreService.FeatureCapabilitiesResponse with

Field number Optional Message type Field name Default
12 [X] CapabilitiesResponse gncs

and has

Field number Optional Message type Field name Default
1 [X] uint32 np_version
DisplayAttributes
Field number Optional Message type Field name Default
1 [X] uint32 width_px
2 [X] uint32 height_px
3 [X] uint32 max_byte_size
4 [X] uint32 quality

CalendarService

Field number Optional Message type Field name Default
1 [X] CalendarEventsRequest calendar_events_request
2 [X] CalendarEventsResponse calendar_events_response
CalendarEventsRequest
Field number Optional Message type Field name Default
1 [X] uint64 start_date
2 [X] uint64 end_date
3 [X] bool include_organizer 0
4 [X] bool include_title 1
5 [X] bool include_location 1
6 [X] bool include_description 0
7 [X] bool include_start_date 1
8 [X] bool include_end_date 0
9 [X] bool include_all_day 0
10 [X] uint32 max_organizer_length 0
11 [X] uint32 max_title_length 0
12 [X] uint32 max_location_length 0
13 [X] uint32 max_description_length 0
14 [X] uint32 max_events 100
CalendarEventsResponse

Enums:

ResponseStatus = {UNKNOWN_RESPONSE_STATUS=0, OK, INVALID_DATE_RANGE}
| Field number | Optional | Message type | Field name | Default | | --- | --- | --- | --- | --- | | 1 | [X] | ResponseStatus | status || | 2 | repeated | CalendarEvent | events ||
CalendarEvent
Field number Optional Message type Field name Default
1 [X] string organizer
2 [X] string title
3 [X] string location
4 [X] string description
5 [X] uint64 start_date
6 [X] uint64 end_date
7 [X] bool all_day
8 repeated uint32 reminder_time_in_secs

ConnectIQHTTPService

Optional messages:

Field number Optional Message type Field name Default
1 [X] ConnectIQHTTPRequest connect_iq_http_request
2 [X] ConnectIQHTTPResponse connect_iq_http_response
3 [X] ConnectIQImageRequest connect_iq_image_request
4 [X] ConnectIQImageResponse connect_iq_image_response
5 [X] RawResourceRequest raw_resource_request
6 [X] RawResourceResponse raw_resource_response

Missing from this document:

Field number Optional Message type Field name Default
7 [X] ConnectIQOAuthRequest connect_iq_oauth_request
8 [X] ConnectIQOAuthResponse connect_iq_oauth_response
9 [X] ConnectIQOAuthCompleteRequest connect_iq_oauth_complete_request
10 [X] ConnectIQOAuthCompleteResponse connect_iq_oauth_complete_response
11 [X] OpenWebpageNotification open_webpage_notification
ConnectIQHTTPRequest

Enums:

HTTPMethod = {UNKNOWN = 0, GET, PUT, POST, DELETE, PATCH, HEAD}
ResponseType = {JSON = 0, URL_ENCODED, PLAIN_TEXT, XML}
Version = {VERSION_1 = 0, VERSION_2}
Field number Optional Message type Field name Default
1 [ ] string url
2 [X] HTTPMethod http_method
3 [X] bytes http_header_fields
4 [X] bytes http_body
5 [X] uint32 max_response_length
6 [X] bool include_http_header_fields_in_response 1
7 [X] bool compress_response_body 0
8 [X] ResponseType response_type
9 [X] Version version VERSION_1
ConnectIQHTTPResponse

Enums:

ResponseStatus = { UNKNOWN=0, OK=100, INVALID_HTTP_HEADER_FIELDS_IN_REQUEST=200, INVALID_HTTP_BODY_IN_REQUEST=201, INVALID_HTTP_METHOD_IN_REQUEST=202, NETWORK_REQUEST_TIMED_OUT=300, INVALID_HTTP_BODY_IN_NETWORK_RESPONSE=400, INVALID_HTTP_HEADER_FIELDS_IN_NETWORK_RESPONSE=401, NETWORK_RESPONSE_TOO_LARGE=402, INSECURE_REQUEST=1001 }
Field number Optional Message type Field name Default
1 [X] ResponseStatus status
2 [X] int32 http_status_code
3 [X] bytes http_body
4 [X] bytes http_header_fields
5 [X] uint32 inflated_size
6 [X] ConnectIQHTTPRequest.ResponseType response_type
ConnectIQImageRequest

Enums:

Dithering = { NONE=0, FLOYD_STEINBERG }
Field number Optional Message type Field name Default
1 [ ] string url
2 [ ] uint32 partNumber
3 [X] uint32 max_width
4 [X] uint32 max_height
5 [X] uint32 max_size
6 [X] bytes palette
7 [X] Dithering dithering
8 [X] bool use_data_xfer
ConnectIQImageResponse

Enums:

ResponseStatus = {UNKNOWN=0, OK=100, NETWORK_REQUEST_TIMED_OUT=200, IMAGE_TOO_LARGE=300}
Field number Optional Message type Field name Default
1 [X] ResponseStatus status
2 [X] int32 http_status_code
3 [X] bytes image_data
4 [X] uint32 width
5 [X] uint32 height
6 [X] uint32 inflated_size
7 [X] DataTransferItem (from gdi_data_types) xfer_data
RawResourceRequest

Enums:

HTTPMethod = {UNKNOWN=0, GET, PUT, POST, DELETE, PATCH, HEAD}
| Field number | Optional | Message type | Field name | Default | | --- | --- | --- | --- | --- | | 1 | [ ] | string | url || | 2 | [X] | uint32 | max_size || | 3 | [X] | HTTPMethod | method | GET | | 4 | [X] | string | body || | 5 | repeated | HTTPHeader | headers || | 6 | [X] | bool | use_data_xfer || | 7 | [X] | bytes | raw_body || | 8 | repeated | MultipartForm | forms || | 9 | [X] | int32 | connection_timeout_seconds | 60 | | 10 | [X] | int32 | read_timeout_seconds | 60 |
HTTPHeader
Field number Optional Message type Field name Default
1 [ ] string key
2 [ ] string value
MultipartForm
Field number Optional Message type Field name Default
1 [X] string name
2 [X] string filename
3 [X] string content_type
4 [X] bytes resource_data
5 [X] DataTransferItem xfer_data
RawResourceResponse

Enums:

ResponseStatus = { UNKNOWN=0, OK=100, NETWORK_REQUEST_TIMED_OUT=200, FILE_TOO_LARGE=300, DATA_TRANSFER_ITEM_FAILURE=400 }
Field number Optional Message type Field name Default
1 [X] ResponseStatus status
2 [X] int32 http_status_code
3 [X] bytes resource_data
4 [X] DataTransferItem xfer_data
5 repeated HTTPHeader headers
HTTPHeader
Field number Optional Message type Field name Default
1 [ ] string key
2 [ ] string value

DataTransferService

Field number Optional Message type Field name Default
1 [X] DataDownloadRequest data_download_request
2 [X] DataDownloadResponse data_download_response
3 [X] InitiateDataUploadRequest initiate_data_upload_request
4 [X] InitiateDataUploadResponse initiate_data_upload_response
5 [X] DataUploadRequest data_upload_request
6 [X] DataUploadResponse data_upload_response
7 [X] DataUploadCanceledNotification data_upload_canceled_notification
8 [X] FileAccessItemRequest file_access_item_request
9 [X] FileAccessItemResponse file_access_item_response
CapabilitiesRequest

This message extends CoreService.FeatureCapabilitiesRequest with

Field number Optional Message type Field name Default
14 [X] CapabilitiesRequest data_xfer_request

and has

Field number Optional Message type Field name Default
1 [X] uint32 service_version
CapabilitiesResponse

This message extends CoreService.FeatureCapabilitiesResponse with

Field number Optional Message type Field name Default
14 [X] CapabilitiesResponse data_xfer_response
DataDownloadRequest
Field number Optional Message type Field name Default
1 [ ] uint32 id
2 [ ] uint32 offset
3 [X] uint32 max_chunk_size 4096
DataDownloadResponse

Enums:

Status = {UNKNOWN=0, SUCCESS, INVALID_ID, INVALID_OFFSET}
| Field number | Optional | Message type | Field name | Default | | --- | --- | --- | --- | --- | | 1 | [ ] | Status | status || | 2 | [ ] | uint32 | id || | 3 | [ ] | uint32 | offset || | 4 | [X] | bytes | payload ||
InitiateDataUploadRequest
Field number Optional Message type Field name Default
1 [ ] uint32 id
InitiateDataUploadResponse

Enums:

Status = {UNKNOWN=0, OK, INVALID_ID}
| Field number | Optional | Message type | Field name | Default | | --- | --- | --- | --- | --- | | 1 | [ ] | uint32 | id || | 2 | [ ] | Status | status ||
DataUploadRequest
Field number Optional Message type Field name Default
1 [ ] uint32 id
2 [ ] uint32 offset
3 [ ] bytes payload
DataUploadResponse

Enums:

Status = {UNKNOWN=0, SUCCESS, INVALID_ID, INVALID_OFFSET, SIZE_MISMATCH, ABORT}
| Field number | Optional | Message type | Field name | Default | | --- | --- | --- | --- | --- | | 1 | [ ] | uint32 | id || | 2 | [ ] | Status | status ||
DataUploadCanceledNotification
Field number Optional Message type Field name Default
1 [ ] uint32 id
FileAccessItemRequest

Enums:

Latency = { STANDARD=0, SOON, IMMEDIATE, DURING_ACTIVITY }
| Field number | Optional | Message type | Field name | Default | | --- | --- | --- | --- | --- | | 1 | [X] | uint32 | data_xfer_id || | 2 | [X] | Latency | expected_latency |STANDARD|
FileAccessItemResponse

Enums:

Status = { UNKNOWN=0, OK, INVALID_ID }
Field number Optional Message type Field name Default
1 [x] status status
2 [x] uint32 data_xfer_id
3 [x] uuid file_access_item_uid

GPS CPE updates

GPS CPE updates are requested by the watch using the ConnectIQHTTPService.RawResourceRequest, requesting the URL [https://api.gcs.garmin.com/ephemeris/cpe/sony/lle?coverage=WEEKS_1&constellations=GPS,GLONASS,GALILEO,QZSS]. Most headers are not necessary; for requests the header accept is sufficient. For caching if-none-match can be sent as well. The relevant response headers are content-type, content-length, date, and possibly etag for caching purposes. After the phone has download the requested file, it will send a ConnectIQHTTPService.RawResourceResponse with the received status code and possibly filtered headers to the watch. If use_data_xfer was set in the RawResourceRequest, the phone will create a transferId (data_xfer_id, possibly sequential starting at 0) to provide in addition to the file's length to the watch. Otherwise it will send the data directly using the resource_data field. In case of the former the watch will initiate a series of DataTransferService.DataDownloadRequest messages with various offsets and the provided data_xfer_id to receive fragments via a series of DataTransferService.DataDownloadResponse messages.