Skip to content

UncleGravity/simble

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BLE Sensor Simulator

⚠️ 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.

Features

  • 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

Quick Start

Installation

With Nix (recommended):

nix run github:UncleGravity/simble -- <args>

With npm:

npm install
npm run build

Requirements: Node.js 22+, Bluetooth 4.0+ adapter (for BLE mode)

Generate Synthetic Data

# 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 FIT Files

# 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,power

Commands

play - Generate Synthetic Data

Simulate sensors with random values in realistic ranges.

npm start -- play [options]

Options:

  • --protocols <list>: Comma-separated protocols (required)
    • heart_rate: 60-180 bpm
    • power: 50-400 watts
    • csc: Cycling speed + cadence
    • rsc: Running speed
    • battery: 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) or ble
  • --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 ble

replay - Play Back FIT Files

Replay real workout data with original timing.

npm start -- replay [options]

Options:

  • --file <path>: Path to FIT file (required)
  • --format <type>: File format - fit or csv (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) or ble
  • --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"

BLE Protocols

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

Output Modes

Stdout (Default)

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}

BLE (Bluetooth)

Broadcasts as real BLE peripheral:

npm start -- play --protocols heart_rate --transport ble

Requirements:

  • 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

Development

Project Structure

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

Key Concepts

Branded Types: Type-safe value objects with runtime validation

type Bpm = number & Brand<"Bpm">  // 30-220 bpm validated

Protocol 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

Scripts

npm run dev          # Run with tsx (no build)
npm run build        # TypeScript compilation
npm run typecheck    # Type check only
npm test             # Run tests

Testing

# Run all tests
npm test

# With coverage
npm test -- --coverage

# Watch mode
npm test -- --watch

Architecture

See docs/ARCHITECTURE.md.

Contributing

See docs/PROJECT_GUIDELINES.md.

Roadmap

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

License

MIT

About

Bletooth Low Energy Peripheral Simulation CLI

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published