# ANT+ to Bluetooth LE Bridge

Bridge an ANT+ cycling power trainer over Bluetooth Low Energy, allowing modern devices that don't support 
ANT+ to receive power and cadence data.

## Why this exists

Modern training apps and devices (phone apps, many power meter displays) support Bluetooth LE but lack ANT+ radios. 
Previously, hardware-based Bluetooth-to-ANT+ bridges were available for this purpose, but these have now been 
discontinued. This project provides a simple, software-based alternative using a standard USB ANT+ dongle. 
This bridge listens to ANT+ data from a wired trainer and re-broadcasts it as a standard Cycling Power Profile 
service over BLE.

## How it works

1. Opens a USB ANT+ dongle (vendor ID `0x0fcf`) and listens for broadcast messages from a specific trainer device number.
2. Parses power (Watts) and cadence (RPM) from the trainer's ANT+ data pages.
3. Exposes a Cycling Power Measurement BLE service via the system's Bluetooth adapter, updating values as new ANT+ messages arrive.

## Requirements

- Linux
- D-Bus (for BlueZ Bluetooth management)
- A Bluetooth adapter
- An ANT+ USB dongle
- An ANT+ cycling power trainer

**Note:** This program must be run as root to access the USB dongle.

## Tested hardware

- USB dongle: ANT USBStick2 (Dynastream Innovations, vendor `0x0fcf`, product `0x1008`)

## Setup

The Linux `usbserial` driver must be prevented from claiming the ANT+ dongle. Create the following udev rule:

```bash
sudo tee /etc/udev/rules.d/99-ant-usb.rules > /dev/null <<EOF
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fcf", ATTRS{idProduct}=="1008", ENV{MODALIAS}="ignore"
EOF
```

The vendor id and product id above can be obtained from the `dmesg` output after inserting the USB dongle. 

Then reload the rules and reconnect the dongle:

```bash
sudo modprobe -r usb_serial_simple
sudo udevadm control --reload-rules
sudo udevadm trigger
```

Verify the dongle is no longer claimed by `usbserial`:

```bash
dmesg | tail -5
```

Expected output:
```
usb 3-1.2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 3-1.2.1: Product: ANT USBStick2
usb 3-1.2.1: Manufacturer: Dynastream Innovations
```

## Installation

```bash
make build
```

The binary is built to `bin/bridge`.

## Usage

```bash
# Use defaults (device 3001)
./bin/bridge

# Custom trainer device
./bin/bridge --device 0xbb9

# Custom vendor/product IDs
./bin/bridge --vendor 0x0fcf --product 0x1008 --device 3001
```

### CLI Flags

| Flag | Default | Description |
|------|---------|-------------|
| `--vendor` | `0x0fcf` | USB vendor ID (hex or decimal, e.g. `0x0fcf` or `4047`) |
| `--product` | `0x1008` | USB product ID (hex or decimal) |
| `--device` | `3001` | ANT+ device number (hex or decimal, e.g. `3001` or `0xbb9`) |
| `--help` | | Show help |
| `--version` | | Show version info |

## Output

```
2026-05-26 11:00:34 ANT Bridge abc1234 built 2026-05-26T11:00:00
2026-05-26 11:00:34 vendor: 0x0fcf/4047
2026-05-26 11:00:34 product: 0x1008/4104
2026-05-26 11:00:34 device: 0xbb9/3001
2026-05-26 11:00:34 BLE advertising...
2026-05-26 11:00:34 bt: watts: 150  rpm: 80  completedRevs: 1234  lastRevTime: 4890 processingTime: 250us
```

## Development

```bash
make build    # Build with ldflags (version, build time)
make clean    # Remove build artifacts
```

## Known issues

It has been observed that during use the wattage sometimes drops briefly to 0 but then quickly recovers.
Logging will hopefully pinpoint the issue should it occur again. 
