Need help with gymnasticon?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

143 Stars 20 Forks MIT License 63 Commits 6 Opened issues


Make obsolete and/or proprietary exercise bikes work with popular cycling training apps like Zwift, TrainerRoad, Rouvy and more.

Services available


Need anything else?

Contributors list


Gymnasticon enables obsolete and/or proprietary exercise bikes to work with Zwift and other training apps. Support for new bikes can be added easily. The diagram below shows an example of how it works with the Flywheel Home Bike.

Bikes tested

  • Flywheel
  • Peloton Bike (requires an additional cable)
  • Schwinn IC4/IC8 aka Bowflex C6
  • LifeFitness IC5 (probably works)

Apps and devices tested

Any software, bike computer or watch that supports standard Bluetooth LE and ANT+ power meter and cadence sensors should work, including:

  • Zwift
  • TrainerRoad
  • Rouvy
  • RGT
  • FulGaz
  • Peloton iOS/Android (BLE CSC cadence only)
  • Garmin Fenix (requires ANT+ stick)
  • Garmin Edge
  • Wahoo Elemnt Bolt (requires ANT+ stick)

Platforms tested

Raspberry Pi Zero W is recommended for best user experience. Any recent Linux or macOS system should be able to run Gymnasticon.

  • Raspbian Buster on Raspberry Pi Zero W
  • Raspbian Buster on Raspberry Pi 4
  • macOS 10.14+
  • Debian Buster on x86-64

Note: If using a Bluetooth LE bike (e.g. Flywheel) a Bluetooth LE 4.1+ adapter with multi-role capability is required.

Quick Start: Install Gymnasticon SD card image

This is the easiest way to get up and running on a Raspberry Pi.


  1. A Raspberry Pi Zero W or Raspberry Pi 4
  2. A compatible micro-SD card (8GB+)
  3. Access to a computer with an SD card slot
  4. A program to write SD card images like Raspberry Pi Imager or


  1. Download the latest Gymnasticon SD card image
  2. Write the image to the SD card using Raspberry Pi Imager or
  3. Optionally add a config file to the SD card (not necessary for Flywheel or Peloton, see below)
  4. Insert the SD card in the Raspberry Pi, power it up and wait a minute
  5. Start pedaling and Gymnasticon should appear in the Zwift device list

Config file:

If using another bike than Flywheel or Peloton, create and adapt a gymnasticon.json file within the boot folder of the SD card.

The following example configures Gymnasticon to look for a Schwinn IC4 bike and to reduce its power measurement values by 8%:

  "bike": "ic4",
  "power-scale": 0.92

See below for additional configuration options.

Optional extra steps:

  1. Setup networking and remote access so you can check logs, perform upgrades, and do clean shutdowns, etc.

Note: It's easiest to leave the Raspberry Pi plugged in once it's set up. Safely shutting it down requires first logging in and halting the system at the command-line with

sudo halt


Flywheel bike

  • Check that there are fresh batteries in the bike (2x D batteries)
  • Check that the bike is calibrated:

Peloton bike (with passive wiring)

  • Note that stats are only broadcast during a class or Just Ride session

Manual install

Try the Quick Start first. Otherwise read on for how to install Gymnasticon and its dependencies manually.


  • Node.JS 12.16.1+

    • armv6l binaries (Raspberry Pi)
    • x64 binaries
  • On Linux (including Raspberry Pi)

    • sudo apt-get install libudev-dev
      (required by node-bluetooth-hci-socket)

Note: Your user must have permission to access the Bluetooth adapter and advertise services.


npm install -g gymnasticon

To run as an unprivileged user:

# this gives cap_net_raw+eip to all node programs not just gymnasticon
sudo setcap cap_net_raw+eip $(eval readlink -f $(which node))

To run at boot time, restart on exit and to avoid giving

to the node binary it is recommended to run under systemd. See the
from this repository for an example systemd unit file.
sudo cp gymnasticon.service /etc/systemd/system
sudo systemctl enable gymnasticon
sudo systemctl start gymnasticon

To view the output of Gymnasticon running under systemd:

journalctl -u gymnasticon -f

CLI options

Note: The CLI options below can also be used in the config file.

--bike ic4
on the command-line is the same as
in the config file.
$ gymnasticon --help
 _ \<_ gymnasticon v1.3.0 usage: options:> load options from json file        [string]
           [string] [choices: "flywheel", "peloton", "ic4", "bot", "autodetect"]
                                                         [default: "autodetect"]
  --bike-connect-timeout                          [number] [default: 0]
  --bike-receive-timeout                          [number] [default: 4]
  --bike-adapter           for bike connection           [default: "hci0"]
  --peloton-path           usb serial device path
                                              [string] [default: "/dev/ttyUSB0"]
  --bot-power              initial bot power                     [number]
  --bot-cadence            initial bot cadence                     [number]
  --bot-host               for power/cadence control over udp     [string]
  --bot-port               for power/cadence control over udp     [number]
  --server-adapter         for app connection            [default: "hci0"]
  --server-name            used for Bluetooth advertisement
                                                        [default: "Gymnasticon"]
  --server-ping-interval   ping app when user not pedaling
                                                           [number] [default: 1]
  --ant-device-id          ANT+ device id for bike power broadcast
                                                       [number] [default: 11234]
  --power-scale            scale watts by this multiplier
                                                           [number] [default: 1]
  --power-offset           add this value to watts  [number] [default: 0]
  --version               Show version number                          [boolean]
  -h, --help              Show help                                    [boolean]


git clone
cd gymnasticon
npm run build
npm link
gymnasticon --help

HOWTO: Add support for a bike

It should be trivial to add support for other proprietary bikes, so long as there is a means of getting realtime-ish cadence/power data from them.

  1. Implement a bikeclient in src/bikes
  2. Add cli options to src/app/cli-options
  3. Add function to instantiate the bikeclient with the cli options to src/bikes/index.js



More info

Read the development notes here.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.