docs: add README with setup instructions and tested hardware
Add comprehensive README.md covering project purpose, CLI usage, and troubleshooting. Document the udev rule needed to prevent usbserial from claiming the ANT+ dongle. Add Tested hardware section listing the ANT USBStick2 and update setup.md dmesg output accordingly. Note: the bridge must be run as root to access the USB dongle.
This commit is contained in:
parent
b24513fcc3
commit
ed4f75a93d
109
README.md
Normal file
109
README.md
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# 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+ bridge boxes 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
|
||||||
|
```
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
The Makefile injects the git commit hash and build timestamp via ldflags for version information.
|
||||||
14
setup.md
14
setup.md
@ -21,11 +21,13 @@ sudo udevadm trigger
|
|||||||
|
|
||||||
Output of dmesg
|
Output of dmesg
|
||||||
```
|
```
|
||||||
[20167.459968] usb 3-2.2.1: new full-speed USB device number 16 using xhci_hcd
|
[25649.007539] usb 3-1.2.1: USB disconnect, device number 40
|
||||||
[20167.550486] usb 3-2.2.1: New USB device found, idVendor=0fcf, idProduct=1008, bcdDevice= 1.00
|
[25651.523030] usb 3-1.2.1: new full-speed USB device number 41 using xhci_hcd
|
||||||
[20167.550497] usb 3-2.2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
|
[25651.629681] usb 3-1.2.1: New USB device found, idVendor=0fcf, idProduct=1008, bcdDevice= 1.00
|
||||||
[20167.550501] usb 3-2.2.1: Product: ANT USBStick2
|
[25651.629693] usb 3-1.2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
|
||||||
[20167.550503] usb 3-2.2.1: Manufacturer: CYCPLUS
|
[25651.629697] usb 3-1.2.1: Product: ANT USBStick2
|
||||||
[20167.550506] usb 3-2.2.1: SerialNumber: 123
|
[25651.629700] usb 3-1.2.1: Manufacturer: Dynastream Innovations
|
||||||
|
[25651.629703] usb 3-1.2.1: SerialNumber: 123
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user