Overview
The EVENTS_FROM_STRAP characteristic (UUID: 0x61080004, Handle: 0x0015) sends notification packets containing event data. These packets appear to track various activities and state changes, though their exact purpose is not fully understood.
Characteristic Details
| Property | Value |
|---|
| UUID | 0x61080004 |
| Name | EVENTS_FROM_STRAP |
| Handle | 0x0015 |
| Writable | No |
| Readable | No |
| Notifiable | Yes |
Event Packet Types
Type 1: Extended Event Packets (36 bytes)
These are the most common event packets received:
Packet Structure
| Field | Bytes | Offset | Example | Description |
|---|
| Header | 3 | 0-2 | aa2400fa30 | Fixed header |
| Counter | 1 | 3 | b0 | Sequential counter |
| Event Type | 2 | 4-5 | 0300 | Event category (little-endian) |
| Unix Time | 4 | 6-9 | 2e316966 | Timestamp (little-endian) |
| Field 1 | 2 | 10-11 | 901f | Unknown data |
| Field 2 | 2 | 12-13 | 1400 | Unknown data |
| Field 3 | 2 | 14-15 | 02e9 | Unknown data |
| Field 4 | 2 | 16-17 | 0000 | Unknown data |
| Field 5 | 2 | 18-19 | 00e9 | Unknown data |
| Field 6 | 2 | 20-21 | 0e00 | Unknown data |
| Field 7 | 2 | 22-23 | 0001 | Unknown data |
| Flags | 5 | 24-28 | 010f030100 | Status flags |
| Value | 1 | 29 | 2f | Some counter/value |
| Marker | 1 | 30 | 01 | Always 01 |
| Padding | 1 | 31 | 00 | Zero padding |
| Reserved | 3 | 32-34 | 000000 | Reserved bytes |
| Checksum | 4 | 35-38 | 699d4a60 | CRC-32 checksum |
Real Examples
Header Cnt Type Unix Time Data Checksum
aa2400fa30 b0 0300 2e316966 901f140002e900 0000e90e0000 010f030100 2f01000000 699d4a60
aa2400fa30 64 0300 6a316966 d02e140002f100 0000ed0e0000 010104010 2e01000000 2d6beb1e
aa2400fa30 28 0300 a6316966 703d140002f900 0000f00e0000 010137040100 2d01000000 50e4148e
aa2400fa30 f3 0300 e2316966 584c1400020101 0000f20e0000 010131050100 2c01000000 0a6472e1
aa2400fa30 57 0300 1e326966 a05a1400020901 0000f60e0000 010123060100 2b01000000 b6aff508
aa2400fa30 6b 0300 5a326966 5869140002 1101 0000fb0e0000 010115070100 2b01000000 b584c4fc
aa2400fa30 76 0300 96326966 a877140002 1901 00004a0f0000 010107080100 2a01000000 f6cfde23
aa2400fa30 87 0300 d3326966 c805140002 2101 0000480f0000 010135080100 2901000000 7586b95f
aa2400fa30 a1 0300 0f336966 d013140002 2901 00004b0f0000 01012f090100 2801000000 b7d66926
aa2400fa30 ac 0300 4b336966 f020140002 3101 0000480f0000 01011a0100 2701000000 5b22a14b
aa2400fa30 b7 0300 87336966 682e140002 3901 00004f0f0000 0101130b0100 2601000000 bc513013
aa2400fa30 c5 0300 c3336966 f03b140002 4101 0000500f0000 010105c0100 2501000000 2849050a
Type 2: Short Event Packets (16 bytes)
A shorter event format also appears:
Packet Structure
| Field | Bytes | Offset | Example | Description |
|---|
| Header | 3 | 0-2 | aa10005730 | Fixed header (different from Type 1) |
| Counter | 1 | 3 | 5b | Sequential counter |
| Event Code | 2 | 4-5 | 2100 | Event type code |
| Unix Time | 4 | 6-9 | 3f326966 | Timestamp (little-endian) |
| Data | 2 | 10-11 | 6854 | Event-specific data |
| Reserved | 2 | 12-13 | 0000 | Zero padding |
| Checksum | 4 | 14-17 | b0b2435b | CRC-32 checksum |
Real Examples
Header Cnt Code Unix Time Data Pad Checksum
aa10005730 5b 2100 3f326966 6854 0000 b0b2435b
aa10005730 65 2200 45326966 a866 0000 093b5aa6
aa10005730 66 1800 48326966 3012 0000 ef5360f0
aa10005730 81 1800 ba326966 2873 0000 9b28989f
aa10005730 6a 2100 e45e6866 e068 0000 323b066b
aa10005730 6e 2200 e85e6866 2843 0000 1489a6e0
aa10005730 70 1800 135f6866 f810 0000 f05e2f2f
aa10005730 75 1500 1c5f6866 b003 0000 55066632
aa10005730 76 0700 1c5f6866 a005 0000 ac1a4bdc
Event Codes
Based on the observed packets, event codes include:
| Code | Decimal | Observations |
|---|
0300 | 3 | Most common, appears in Type 1 packets |
1800 | 24 | Appears in Type 2 packets |
2100 | 33 | Appears in Type 2 packets |
2200 | 34 | Appears in Type 2 packets |
1500 | 21 | Rare, appears in Type 2 packets |
0700 | 7 | Rare, appears in Type 2 packets |
The exact meaning of these event codes is not yet documented. They do not directly correspond to activity start/end times or alarm events.
Timestamp Analysis
All event packets contain Unix timestamps, but these timestamps do not correspond to:
- Activity start times
- Activity end times
- Alarm trigger times
- Sync initiation times
The purpose of these timestamps remains unclear. They may represent:
- Internal device state changes
- Background processing events
- Data logging markers
- Sensor calibration events
Parsing Examples
Parse Type 1 (36-byte) Event
import struct
from datetime import datetime
def parse_type1_event(packet_hex):
"""Parse 36-byte event packet"""
packet = bytearray.fromhex(packet_hex.replace(' ', ''))
if len(packet) != 36:
raise ValueError(f"Expected 36 bytes, got {len(packet)}")
header = packet[0:3].hex()
counter = packet[3]
event_type = struct.unpack('<H', packet[4:6])[0]
unix_time = struct.unpack('<I', packet[6:10])[0]
dt = datetime.fromtimestamp(unix_time)
# Parse data fields
fields = []
for i in range(10, 24, 2):
val = struct.unpack('<H', packet[i:i+2])[0]
fields.append(val)
flags = packet[24:29].hex()
value = packet[29]
marker = packet[30]
checksum = packet[32:36].hex()
return {
'header': header,
'counter': counter,
'event_type': event_type,
'unix_timestamp': unix_time,
'datetime': dt.isoformat(),
'data_fields': fields,
'flags': flags,
'value': value,
'marker': marker,
'checksum': checksum
}
# Example
event = "aa2400fa30 b0 0300 2e316966 901f140002e900 0000e90e0000 010f030100 2f01000000 699d4a60"
result = parse_type1_event(event)
print(f"Event type: {result['event_type']}")
print(f"Timestamp: {result['datetime']}")
print(f"Counter: {result['counter']}")
Parse Type 2 (16-byte) Event
def parse_type2_event(packet_hex):
"""Parse 16-byte event packet"""
packet = bytearray.fromhex(packet_hex.replace(' ', ''))
if len(packet) != 16:
raise ValueError(f"Expected 16 bytes, got {len(packet)}")
header = packet[0:3].hex()
counter = packet[3]
event_code = struct.unpack('<H', packet[4:6])[0]
unix_time = struct.unpack('<I', packet[6:10])[0]
dt = datetime.fromtimestamp(unix_time)
data = struct.unpack('<H', packet[10:12])[0]
checksum = packet[12:16].hex()
return {
'header': header,
'counter': counter,
'event_code': event_code,
'unix_timestamp': unix_time,
'datetime': dt.isoformat(),
'data': data,
'checksum': checksum
}
# Example
event = "aa10005730 5b 2100 3f326966 6854 0000 b0b2435b"
result = parse_type2_event(event)
print(f"Event code: 0x{result['event_code']:04x}")
print(f"Timestamp: {result['datetime']}")
print(f"Data: 0x{result['data']:04x}")
Monitoring Events
To receive event notifications, subscribe to the EVENTS_FROM_STRAP characteristic:
import asyncio
from bleak import BleakClient
EVENTS_UUID = "61080004-8d6d-82b8-614a-1c8cb0f8dcc6"
def event_handler(sender, data):
"""Handle incoming event notifications"""
print(f"Event received: {data.hex()}")
# Determine packet type by length
if len(data) == 36:
event = parse_type1_event(data.hex())
print(f"Type 1 Event: {event}")
elif len(data) == 16:
event = parse_type2_event(data.hex())
print(f"Type 2 Event: {event}")
else:
print(f"Unknown event format: {len(data)} bytes")
async def monitor_events(address):
async with BleakClient(address) as client:
# Subscribe to notifications
await client.start_notify(EVENTS_UUID, event_handler)
# Keep connection alive
print("Monitoring events... (Ctrl+C to stop)")
await asyncio.sleep(3600) # Monitor for 1 hour
await client.stop_notify(EVENTS_UUID)
# Run
address = "XX:XX:XX:XX:XX:XX"
asyncio.run(monitor_events(address))
Common Patterns
Counter Behavior
Both packet types include a counter byte that:
- Increments sequentially
- Wraps around at 256 (0xFF → 0x00)
- Is independent for each packet type
- Not validated - packets with incorrect counters are still processed
Checksum Validation
All event packets include CRC-32 checksums:
- Calculated over all bytes except the checksum itself
- Uses custom CRC-32 parameters (see Packet Formats)
- Device validates checksums but not strictly enforced
Unknown Fields
The purpose of most fields in event packets remains unknown. Further reverse engineering is needed to understand:
- What triggers each event type
- The meaning of data fields
- How event codes map to device states
- Why timestamps don’t match observable events