As a regular Zwifter, I use a Life Fitness IC5 spinning bike (2020) that broadcasts power and cadence over ANT+.
The Problem
Modern devices only support Bluetooth, requiring an ANT+ bridge such as the North Pole Engineering CABLE or the Viiiiva Heart Rate Strap. Unfortunately, both are discontinued. Also, the European Radio Equipment Directive requires encryption for wireless transmission of personal data and is helping to end ANT+. The CABLE replacements WYUR and CORD from North Pole Engineering are also unavailable.
The Solution
Rather than wait for my CABLE to fail, and having to replace my perfectly working spinning bike because of this, I wrote my own ANT+ to Bluetooth bridge in Go. This runs on Debian with a USB ANT+ dongle. The architecture is straightforward. An Ant module receives ANT+ events and puts them on a Channel from where the Bluetooth module reads them:
The key challenge: ANT+ broadcasts instantaneous RPM, while Bluetooth requires cumulative revolution counts and a last-revolution timestamp.
Technical Challenges
Three issues required custom solutions:
- USB reliability: The ANT+ library’s USB handling wasn’t robust enough, so I wrote my own to support hot-plugging the dongle.
- Recovery from bicycle pauzes: When the bike stops transmitting (e.g. during a break), the bridge now detects 10 seconds of inactivity and reinitializes automatically. Without this it did not recover.
- Restarts or crashes of the bridge: When the bridge restarts it resets the bluetooth interface. This causes the bike to automatically reconnect. There must be a proper way to do it but life is too short to find out.
- Crash robustness: A script runs the bridge and simply restarts it when it crashes. Crashes still can occur occasionally although haven’t seen them while cycling.
- Sleep prevention: Wrapped the bridge in
systemd-inhibitto prevent the PC from sleeping mid-ride:
systemd-inhibit --what=idle:sleep --why="Do not interrupt cycling" $( dirname $0 )/bin/bridge "$@"
Physical challenges
During initial development I was a lot on the bike trying to get the ant+ data to show. After development I was still a lot on the bike.
Conclusion
The bridge has been running reliably across sessions from 30 minutes to over 2 hours. The code is available here and supports ANT+ dongles that identify as “Dynastream Innovations”. It’s not perfect, but it works well — pull requests welcome.