Overview
After requesting a batch using the sync process, the device sends a burst of large 96-byte packets on the DATA_FROM_STRAP characteristic. Each packet contains detailed physiological measurements including heart rate, respiratory rate, and sensor data.
96-Byte Data Packet Structure
Each data packet is exactly 96 bytes and contains multiple sections:
Packet Layout
| Section | Bytes | Offset | Description |
|---|
| Header | 6 | 0-5 | Packet header and identifiers |
| Time Data | 6 | 6-11 | Timestamp information |
| Unix Timestamp | 4 | 12-15 | Unix time (little-endian) |
| Timestamp Extension | 6 | 16-21 | Extended timestamp data |
| Heart Rate | 1 | 22 | Heart rate in BPM |
| RR Count | 1 | 23 | Number of RR intervals |
| RR Data | 8 | 24-31 | RR interval values (little-endian) |
| Sensor Data | 60 | 32-91 | Extended sensor measurements |
| Checksum | 4 | 92-95 | CRC-32 checksum |
Real Packet Examples
First 31 bytes breakdown:
Header Time? ? Unix Timestamp Ext HR RR RR Data
aa5c00f02f0c 07 8bb7 0900 c8326966 e03c8054cc01 58 01 b902000000000000
aa5c00f02f0c 07 8cb7 0900 c9326966 f0378054cc01 58 01 b502000000000000
aa5c00f02f0c 07 8db7 0900 ca326966 f8328054cc01 58 02 b802b90200000000
aa5c00f02f0c 07 8eb7 0900 cb326966 082e8054cc01 58 01 ce02000000000000
aa5c00f02f0c 07 8fb7 0900 cc326966 10298054cc01 58 01 c102000000000000
aa5c00f02f0c 07 90b7 0900 cd326966 20248054cc01 58 02 df02d30200000000
aa5c00f02f0c 07 91b7 0900 ce326966 281f8054cc01 57 01 f802000000000000
aa5c00f02f0c 07 92b7 0900 cf326966 381a8054cc01 57 01 fb02000000000000
Remaining 65 bytes (sensor data + checksum):
Sensor Data (60 bytes) Checksum
00004563f880c9143cae47afbe5ccf5b3ef6a4753f00008e46ae47afbe5ccf5b3ef6a4753fe50146021c03440282016004010c020c3000000000000002 2dcbe388
0000cf6bff00e8e23b5248afbe66265c3e0078753f0000c8465248afbe66265c3e0078753fe50146022003460282016004010c020c3000000000000002 4d49cb2e
0000f96dff00a7e73b140eafbe298c5b3e715d753f00001046140eafbe298c5b3e715d753fe50146022003470282016004010c020c3000000000000002 833a28fd
0000a16eff0070b43b1fedaebe3d9a5b3ecd34753f00005ac61fedaebe3d9a5b3ecd34753fe50146022003450282016004010c020c3000000000000002 149f6d4f
00008b63ff0041a43b14e6aebea4b05b3e4819753f0000c0c514e6aebea4b05b3e4819753fe50146021e03450282016004010c020c3000000000000002 a4d38c63
00004661ff001bb03b8fcaaebe1fd55b3e0008753f0000b2c68fcaaebe1fd55b3e0008753fe50146021d03440287016004010c020c3000000000000002 2891f236
0000d161ff00f3a43ba480aebe859b5b3ed7e7743f0000e046a480aebe859b5b3ed7e7743fe50146021d03450287016004010c020c3000000000000002 c197f209
0000f961ff0041fd3b7bb4aebeae475b3e1fd9743f000082467bb4aebeae475b3e1fd9743fe50146021d03440287016004010c020c3000000000000002 aec41896
0000a16aff0061c63b48a1aebe3d0a5c3e66aa743f0000d84548a1aebe3d0a5c3e66aa743fe50146021c03440287016004010c020c3000000000000002 dfafea59
00008c6aff00c8b43bec71aebe33c35b3e9ac1743f000050c5ec71aebe33c35b3e9ac1743fe50146021c03440287016004010c020c3000000000000002 76ae1006
Field Details
- Fixed header identifying data packet type
- First byte
aa is common packet start marker
5c00 indicates 96-byte packet length (0x005c = 92 bytes + 4 checksum)
Time Data (6 bytes)
- Byte 0 (
07): Time-related flag or counter
- Bytes 1-2 (
8bb7): Time value (little-endian u16 = 47,003)
- Bytes 3-4 (
0900): Additional time data (little-endian u16 = 9)
Unix Timestamp (4 bytes)
- Standard Unix timestamp in seconds
- Little-endian unsigned 32-bit integer
- Example:
0x6669.32c8 = 1,717,879,496 = June 8, 2024
Heart Rate & Respiratory Rate
HR: 58 # Beats per minute
RR: 01 # Number of RR intervals in this packet
- HR: Direct heart rate value in BPM
- RR Count: Number of RR intervals (0-2 typically)
- When RR count is 2, both intervals are encoded in RR Data field
RR Data (8 bytes)
b902000000000000 # One RR interval
b802b90200000000 # Two RR intervals
- Little-endian encoded RR intervals in milliseconds
- First 2 bytes: First RR interval
- Bytes 3-4: Second RR interval (if RR count = 2)
- Remaining bytes: Padding (zeros)
Examples:
b902 = 0x02b9 = 697ms
b802 = 0x02b8 = 696ms
Sensor Data (60 bytes)
The remaining 60 bytes contain extended sensor information. The exact structure is not fully documented, but appears to include:
- Float values (IEEE 754 single-precision) for various sensors
- Configuration flags and status bytes
- Potentially temperature, acceleration, or other sensor readings
Common patterns observed:
- Bytes often contain repeating
e50146 sequences
- Many fields with
000000 padding
- Float values in scientific notation ranges
Parsing Example
import struct
from datetime import datetime
def parse_data_packet(packet_hex):
"""Parse 96-byte data packet"""
packet = bytearray.fromhex(packet_hex)
# Parse header
header = packet[0:6].hex()
# Parse timestamps
time_flag = packet[6]
time_val = struct.unpack('<H', packet[7:9])[0]
time_extra = struct.unpack('<H', packet[9:11])[0]
# Parse unix timestamp
unix_time = struct.unpack('<I', packet[12:16])[0]
dt = datetime.fromtimestamp(unix_time)
# Parse extended timestamp
timestamp_ext = packet[16:22].hex()
# Parse heart rate and RR
heart_rate = packet[22]
rr_count = packet[23]
# Parse RR intervals
rr_intervals = []
if rr_count >= 1:
rr1 = struct.unpack('<H', packet[24:26])[0]
rr_intervals.append(rr1)
if rr_count >= 2:
rr2 = struct.unpack('<H', packet[26:28])[0]
rr_intervals.append(rr2)
# Parse sensor data (bytes 32-91)
sensor_data = packet[32:92].hex()
# Parse checksum
checksum = packet[92:96].hex()
return {
'header': header,
'time_flag': time_flag,
'time_value': time_val,
'unix_timestamp': unix_time,
'datetime': dt.isoformat(),
'heart_rate': heart_rate,
'rr_count': rr_count,
'rr_intervals_ms': rr_intervals,
'sensor_data': sensor_data,
'checksum': checksum
}
# Example usage
packet = "aa5c00f02f0c078bb70900c8326966e03c8054cc015801b90200000000000000004563f880c9143cae47afbe5ccf5b3ef6a4753f00008e46ae47afbe5ccf5b3ef6a4753fe50146021c03440282016004010c020c30000000000000022dcbe388"
data = parse_data_packet(packet)
print(f"Heart Rate: {data['heart_rate']} BPM")
print(f"Timestamp: {data['datetime']}")
print(f"RR Intervals: {data['rr_intervals_ms']} ms")
Data Streaming vs Batch Retrieval
The same packet format is used in two scenarios:
-
Real-time streaming: When activity or health monitor is active
- Packets sent continuously every second
- Triggered by commands
0x03 (activity) or 0x06 (health monitor)
-
Batch retrieval: During sync process
- Burst of historical packets
- Triggered by batch request command (
0x17)
- Can retrieve days of stored data
The sensor data section (60 bytes) requires additional reverse engineering to fully decode. It likely contains temperature, accelerometer, and other sensor readings, but the exact structure is not yet documented.
- Sync Process - How to trigger batch retrieval
- Events - Event packets on EVENTS_FROM_STRAP
- Commands - Command structure and checksums