Overview
Synheart Wear supports direct Bluetooth LE connections to any standard heart rate monitor. This enables real-time HR streaming without requiring a cloud API or vendor-specific SDK. Supported devices include:- WHOOP (Broadcast Heart Rate mode)
- Polar chest straps (H10, OH1, Verity Sense)
- Wahoo TICKR, TICKR X
- Garmin HRM-Pro, HRM-Dual
- Gym equipment with BLE HR broadcast
- Any device implementing the standard BLE Heart Rate Profile (0x180D)
How It Works
The BLE HRM provider connects to devices advertising the standard Bluetooth Heart Rate Service (0x180D), subscribes to the Heart Rate Measurement characteristic (0x2A37), and parses incoming data per the Bluetooth SIG specification.
Platform Setup
iOS
Add toInfo.plist:
Android
Add toAndroidManifest.xml:
BLUETOOTH_SCAN and BLUETOOTH_CONNECT.
Usage
- Flutter/Dart
- Swift
- Kotlin
API Reference
Methods
| Method | Description | Returns |
|---|---|---|
scan(timeoutMs, namePrefix?) | Scan for nearby BLE HR monitors | List<BleHrmDevice> |
connect(deviceId, sessionId?, enableBattery?) | Connect to a device and start HR streaming | void |
disconnect() | Disconnect from the current device | void |
isConnected() | Check if a device is currently connected | bool |
BleHrmDevice
Returned fromscan():
| Field | Type | Description |
|---|---|---|
deviceId | String | BLE device UUID |
name | String? | Device advertised name |
rssi | int | Signal strength (dBm) |
HeartRateSample
Emitted on the heart rate stream:| Field | Type | Description |
|---|---|---|
tsMs | int | Phone receipt timestamp (ms since epoch) |
bpm | int | Heart rate in beats per minute |
source | String | Always "ble_hrm" |
deviceId | String | BLE device UUID |
deviceName | String? | Device advertised name |
sessionId | String? | Session tag (passed during connect) |
rrIntervalsMs | List<double>? | RR intervals in milliseconds |
rrIntervalsMs availability depends on the device. Polar chest straps typically include RR intervals; WHOOP Broadcast typically does not.
Error Codes
| Code | Meaning |
|---|---|
PERMISSION_DENIED | Bluetooth permission not granted |
BLUETOOTH_OFF | Bluetooth adapter is disabled |
DEVICE_NOT_FOUND | Device not found or connection timed out |
SUBSCRIBE_FAILED | Failed to subscribe to HR characteristic |
DISCONNECTED | Device disconnected unexpectedly |
WHOOP Broadcast Setup
To use WHOOP as a BLE heart rate monitor:- Open the WHOOP app on your phone
- Go to Device Settings (tap your WHOOP device)
- Enable Broadcast Heart Rate
- Your WHOOP will now appear in BLE scans as a standard HR monitor
Reconnection
The BLE HRM provider automatically handles disconnections:- 3 retry attempts with exponential backoff (1s, 2s, 4s)
- After retries are exhausted, a
DISCONNECTEDerror is emitted on the stream - Your app can then prompt the user to reconnect
Limitations
- Single device: Only one BLE HRM device can be connected at a time (v1)
- Phone-side only: Requires the phone to be in BLE range of the HR monitor
- No HRV calculation: Raw RR intervals are provided when available, but HRV calculation is not performed by the provider
- Battery dependent: Battery level monitoring is optional (
enableBattery: trueduring connect)
Architecture
The BLE HRM provider is implemented natively on each platform:| Platform | Implementation | Streaming Pattern |
|---|---|---|
| iOS | CoreBluetooth (CBCentralManager) | AsyncStream<HeartRateSample> |
| Android | Android BLE (BluetoothLeScanner, BluetoothGatt) | SharedFlow<HeartRateSample> |
| Flutter | Platform Channels (MethodChannel + EventChannel) | Stream<HeartRateSample> |
Author: Israel Goytom