⚠️ WIP (Work In Progress) - This project is under active development. APIs and features may change.
Simulate Bluetooth Low Energy fitness sensors. Generate synthetic data or replay real workouts from FIT files.
- 6 BLE Protocols: Heart Rate, Cycling Power, Cycling Speed/Cadence (CSC), Running Speed (RSC), Battery, GPS/Location
- Two Modes:
- Play: Generate synthetic sensor data
- Replay: Play back real workouts from FIT files with accurate timing
- Sport-Aware: Automatically detects cycling vs running activities
- Real BLE: Advertise as actual BLE peripherals (macOS/Linux)
- Flexible Output: BLE broadcasting or stdout for testing
With Nix (recommended):
nix run github:UncleGravity/simble -- <args>With npm:
npm install
npm run buildRequirements: Node.js 22+, Bluetooth 4.0+ adapter (for BLE mode)
# Heart rate only (stdout)
npm start -- play --protocols heart_rate
# Full cycling workout (BLE broadcast)
npm start -- play --protocols heart_rate,power,csc --transport ble
# Custom intervals and ranges
npm start -- play --protocols heart_rate --interval 500 --min 120 --max 180# Replay a cycling workout
npm start -- replay --file workout.fit --format fit
# With BLE broadcasting
npm start -- replay --file workout.fit --format fit --transport ble
# Filter specific sensors
npm start -- replay --file workout.fit --format fit --protocols heart_rate,powerSimulate sensors with random values in realistic ranges.
npm start -- play [options]Options:
--protocols <list>: Comma-separated protocols (required)heart_rate: 60-180 bpmpower: 50-400 wattscsc: Cycling speed + cadencersc: Running speedbattery: 20-100%location_navigation: GPS coordinates (simulates walking)
--interval <ms>: Emit interval in milliseconds (default: 1000)--min <n>: Minimum value for numeric sensors--max <n>: Maximum value for numeric sensors--transport <type>: Output mode -stdout(default) orble--advertise-name <name>: BLE device name (max 10 chars, default: "SimBLE")--log-level <level>: Log verbosity -None,Error,Warning,Info,Debug(default: Info)
Examples:
# Basic heart rate simulation
npm start -- play --protocols heart_rate
# High-intensity cycling workout
npm start -- play --protocols heart_rate,power,csc --min 150 --max 200
# Multiple sensors with BLE
npm start -- play --protocols heart_rate,power,csc,battery,location_navigation --transport bleReplay real workout data with original timing.
npm start -- replay [options]Options:
--file <path>: Path to FIT file (required)--format <type>: File format -fitorcsv(required)--protocols <list>: Filter protocols to replay (optional, replays all by default)--strict: Exit on validation errors (default: false)--transport <type>: Output mode -stdout(default) orble--advertise-name <name>: BLE device name (max 10 chars)--log-level <level>: Log verbosity
Sport Detection:
The simulator automatically detects the sport type from FIT files:
- Cycling files → Creates CSC (Cycling Speed/Cadence) observations
- Running files → Creates RSC (Running Speed) observations
- Mixed/Unknown → Defaults to cycling
Examples:
# Replay entire workout
npm start -- replay --file morning_ride.fit --format fit
# Only heart rate and power
npm start -- replay --file morning_ride.fit --format fit --protocols heart_rate,power
# Broadcast as BLE
npm start -- replay --file race.fit --format fit --transport ble --advertise-name "RACE"| Protocol | ID | Service UUID | Use Case |
|---|---|---|---|
| Heart Rate | heart_rate |
0x180D | Heart rate monitors |
| Cycling Power | power |
0x1818 | Power meters |
| Cycling Speed/Cadence | csc |
0x1816 | Bike speed and cadence sensors |
| Running Speed | rsc |
0x1814 | Running speed pods |
| Battery | battery |
0x180F | Battery level |
| Location & Navigation | location_navigation |
0x1819 | GPS devices |
Outputs JSON events for testing without hardware:
npm start -- play --protocols heart_rate{"timestamp":1699564800000,"protocol":"heart_rate","value":72}
{"timestamp":1699564801000,"protocol":"heart_rate","value":75}Broadcasts as real BLE peripheral:
npm start -- play --protocols heart_rate --transport bleRequirements:
- Bluetooth 4.0+ adapter
- May require sudo/administrator privileges
Testing:
- nRFConnect to scan
- Connect with fitness apps (Zwift, etc.)
Troubleshooting:
- "BLE radio not powered on" → Enable Bluetooth in system settings
- "Permission denied" → Run with
sudo(Linux) or grant Bluetooth permissions (macOS) - "State error" → Close other apps using Bluetooth
src/
├── domain/
│ ├── AppConfig.ts # CLI configuration types
│ ├── observations.ts # Core pipeline data types
│ └── values.ts # Branded types (Bpm, Watts, etc.)
├── protocols/
│ ├── registry.ts # Protocol registry
│ ├── location_navigation.ts # GPS/location protocol
│ ├── heart_rate.ts # Heart rate protocol
│ ├── power.ts # Cycling power protocol
│ ├── etc...
├── adapters/
│ ├── sources/
│ │ ├── fit.ts # FIT file parser
│ │ └── synthetic.ts # Synthetic data generator
│ ├── transport/
│ │ ├── BleTransport.ts # BLE broadcaster
│ │ └── StdoutTransport.ts # BLE broadcaster
│ ├── cli/ # CLI args parsing + handlers
└── main.ts # Entry point
Branded Types: Type-safe value objects with runtime validation
type Bpm = number & Brand<"Bpm"> // 30-220 bpm validatedProtocol Interface: Each sensor implements the same interface
interface SensorProtocol<P> {
generateValue(): Value;
validate(raw: unknown): ParsedObservation;
encode(observation): Buffer;
}Sport-Aware FIT Parsing: Detects activity type and maps fields correctly
- Cycling:
speed+cadence→ CSC protocol - Running:
speed→ RSC protocol
npm run dev # Run with tsx (no build)
npm run build # TypeScript compilation
npm run typecheck # Type check only
npm test # Run tests# Run all tests
npm test
# With coverage
npm test -- --coverage
# Watch mode
npm test -- --watchSee docs/ARCHITECTURE.md.
See docs/PROJECT_GUIDELINES.md.
Completed:
- Support multiple BLE protocols
- Heart Rate
- Power
- CSC
- RSC
- Battery
- Location
- FIT file parsing and replay with sport detection
- Synthetic data generation for testing
- CLI with flexible configuration options
- Type-safe inshallah
In Progress / Planned:
- Replace bleno with custom library
- Add e2e tests
- Improve error handling for unsupported FIT file types
- Add config file support for predefined workout profiles
MIT