Skip to main content

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

PropertyValue
UUID0x61080004
NameEVENTS_FROM_STRAP
Handle0x0015
WritableNo
ReadableNo
NotifiableYes

Event Packet Types

Type 1: Extended Event Packets (36 bytes)

These are the most common event packets received:

Packet Structure

FieldBytesOffsetExampleDescription
Header30-2aa2400fa30Fixed header
Counter13b0Sequential counter
Event Type24-50300Event category (little-endian)
Unix Time46-92e316966Timestamp (little-endian)
Field 1210-11901fUnknown data
Field 2212-131400Unknown data
Field 3214-1502e9Unknown data
Field 4216-170000Unknown data
Field 5218-1900e9Unknown data
Field 6220-210e00Unknown data
Field 7222-230001Unknown data
Flags524-28010f030100Status flags
Value1292fSome counter/value
Marker13001Always 01
Padding13100Zero padding
Reserved332-34000000Reserved bytes
Checksum435-38699d4a60CRC-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

FieldBytesOffsetExampleDescription
Header30-2aa10005730Fixed header (different from Type 1)
Counter135bSequential counter
Event Code24-52100Event type code
Unix Time46-93f326966Timestamp (little-endian)
Data210-116854Event-specific data
Reserved212-130000Zero padding
Checksum414-17b0b2435bCRC-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:
CodeDecimalObservations
03003Most common, appears in Type 1 packets
180024Appears in Type 2 packets
210033Appears in Type 2 packets
220034Appears in Type 2 packets
150021Rare, appears in Type 2 packets
07007Rare, 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

Build docs developers (and LLMs) love