Skip to content
This repository has been archived by the owner on May 8, 2021. It is now read-only.

Indoor Bike Support #10

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c52c804
Add support for treadmills using Bluetooth instead of WiFi
RasPelikan Mar 17, 2020
2c75b80
Show Zwift connection status in console
RasPelikan Mar 21, 2020
fc71863
Add optional shutdown on disconnect
RasPelikan Mar 21, 2020
f2d438b
Add shutdown option for WiFi connected treadmills
RasPelikan Mar 23, 2020
74c6e43
Use exit code 99 for shutdown signals
RasPelikan Mar 28, 2020
e6a315e
Fixes
RasPelikan Mar 28, 2020
45c255f
Use exit code 99 for shutdown signals
RasPelikan Mar 28, 2020
94208ad
Fixes
RasPelikan Mar 28, 2020
bc596a4
Fix reading the treadmills' mode
RasPelikan Mar 28, 2020
83f1c8d
Support zwifit-incline-tracker
RasPelikan Mar 28, 2020
3a9729e
Fix reading the treadmills' mode
RasPelikan Mar 28, 2020
9d1ff51
Pump version of noble to 1.9.2-8 including PR-59
RasPelikan Apr 13, 2020
6bb180a
Improvements
RasPelikan Apr 13, 2020
63ebfcd
Merge remote-tracking branch 'origin/feature/ble' into feature/zwifit…
RasPelikan Apr 13, 2020
be3390d
Merge pull request #1 from tonymyatt/feature/zwifit-incline-tracker
tonymyatt Apr 22, 2020
2a87562
Add files via upload
tonymyatt Apr 25, 2020
a66735a
Indoor Bike Support
tonymyatt Apr 25, 2020
f3c0bc2
Add details on incline for indoor bikes
tonymyatt Apr 25, 2020
781b600
fix typo
tonymyatt Feb 27, 2022
862c95e
Update package-lock.json
aaronjamt Jun 15, 2022
1e51bee
Show current status on website after each update, rather than the pre…
aaronjamt Jun 15, 2022
c948349
Prevent app from crashing 30 seconds after launch when not connected …
aaronjamt Jun 15, 2022
b57f5b0
Merge pull request #2 from aaronjamt/master
tonymyatt Jun 24, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 78 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
# Zwifit

Welcome to the cryptically named Zwifit! This NodeJS app joins Zwift with treadmills running iFit® with Wi-Fi.
Welcome to the cryptically named Zwifit! This NodeJS app joins Zwift with fitness machines (treadmills & indoor bikes)
running iFit® with Wi-Fi/Bluetooth.

**Disclaimer:** I'm not associated with either company. Their trademarks and content are their own.
Heck, they might force me to take this down! But let's enjoy the *run* before they do.

## How This Works

This software connects to your iFit® treadmill over Wi-Fi to observe its speed and incline. It then
This software connects to your iFit® treadmill over Wi-Fi/Bluetooth to observe its speed and incline. It then
broadcasts that information over Bluetooth in a standard protocol that apps like Zwift are able to
understand.
understand. For indoor bikes power and cadence are also observed and gradient is transmitted to the ifit®
bike as incline.

## What Treadmills Are Compatible?
## What Fitness Machines Are Compatible?

At the moment it seems hit or miss on which iFit treadmills with Wi-Fi work, but we are building a spreadsheet
over at the following URL. Look through that. You may also be interested in the TreadSync app, which has a similar
goal to this project, but runs in a slightly different way (on iOS devices).
At the moment it seems hit or miss on which iFit® fitness machines with Wi-Fi/Bluetooth work, but we are building a
spreadsheet over at the following URL. Look through that. You may also be interested in the TreadSync app, which has
a similar goal to this project, but runs in a slightly different way (on iOS devices).

http://bit.ly/TS-compat

## Minimum Requirements

1. A Wi-Fi connected iFit® treadmill; those treadmills that use Bluetooth instead of Wi-Fi likely will *not* work
1. A Wi-Fi/Bluetooth connected iFit® fitness machines (treadmills & indoor bikes)
2. Zwift running on your favorite device
3. A Raspberry Pi ZeroW or 3B running this software (this software works on versions of Mac OS X before Mojave, but our Bluetooth dependency is presently borked on Mojave -- Windows requires an external Bluetooth LE dongle be properly configured).
4. Know the IP address of your treadmill. (I recommend reserving this IP in your router so it doesn't change.)
5. You need to be minimally comfortable with a command line / terminal. Or have a nerdy friend!
4. For Wi-Fi connected treadmills: Know the IP address of your treadmill. (I recommend reserving this IP in your router so it doesn't change.)
5. Indoor bikes are only supported by Bluetooth
6. You need to be minimally comfortable with a command line / terminal. Or have a nerdy friend!

Raspberry Pi Zero W: https://www.amazon.com/CanaKit-Raspberry-Wireless-Complete-Starter/dp/B072N3X39J/ref=sr_1_4?ie=UTF8&qid=1546535245&sr=8-4&keywords=raspberry+pi+zero+w

Expand All @@ -35,15 +38,22 @@ Note: the above is NOT an affiliate link, I don't get anything from you clicking

### Raspbian (Raspberry Pi)

This software works great on a **Raspberry Pi 3b+** or a **Zero W**. Follow all of these steps on your Pi itself, not on
This software works great on a **Raspberry Pi 3b+** or a **Raspberry Pi Zero W**. Follow all of these steps on your Pi itself, not on
your laptop or desktop! The easiest way to do this is to plug a monitor, keyboard and mouse in to your
Pi. Or, if you've set up SSH, you can `ssh` in to your Pi to follow these steps (hint: this option is in the configuration UI).

1. `sudo apt-get update`
2. Install the dependencies we need: `sudo apt-get install nodejs npm git bluetooth bluez libbluetooth-dev libudev-dev`
3. Turn off the system Bluetooth daemon so we can control it: `sudo systemctl disable bluetooth` (to reverse this, change `disable` to `enable`)
4. Turn the Bluetooth chip back on: `sudo hciconfig hci0 up`
5. Give NodeJS access to Bluetooth without sudo: ```sudo setcap cap_net_raw+eip $(eval readlink -f `which node`)```
2. Install the dependencies we need: `sudo apt-get install git bluetooth bluez libbluetooth-dev libudev-dev`
3. Install NodeJS 13.x
1. For **Raspberry Pi 3b+** run `curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash -` and `sudo apt install -y nodejs`
2. For **Raspberry Pi Zero W** use the [unofficial builds](https://github.com/nodejs/unofficial-builds/), because armv61 is not part of the official builds any more. Download the binaries, run
* `mkdir /opt`
* `tar -C /opt -xzvf node-v13.8.0-linux-armv61.tar.gz`
* `echo "export PATH=\$PATH:/opt/node-v13.8.0-linux-armv6l/bin" >> ~/.bashrc`
* exit and re-open terminal to activate changes
4. Turn off the system Bluetooth daemon so we can control it: `sudo systemctl disable bluetooth` (to reverse this, change `disable` to `enable`)
5. Turn the Bluetooth chip back on: `sudo hciconfig hci0 up`
6. Give NodeJS access to Bluetooth without sudo: ``sudo setcap cap_net_raw+eip $(eval readlink -f `which node`)``

### Windows

Expand All @@ -70,15 +80,17 @@ With the software requirements out of the way, you can run the following command
git clone https://github.com/dawsontoth/zwifit.git
cd zwifit
npm install
node app.js
npm start
```

The last command will guide you through connecting to your treadmill. It will save your answers, and
The last command will guide you through connecting to your fitness machines. It will save your answers, and
won't ask you in the future. Your answers are saved in the settings.conf file. To change them, simply
edit settings.conf (or delete it and run `node app.js` again).
edit settings.conf (or delete it and run `npm start` again).

## Automatic Startup

### Using PM2

Do you want this script to run in the background, even when you restart your computer? There are many
ways to accomplish this. Personally, I use a program called PM2.

Expand Down Expand Up @@ -113,18 +125,64 @@ git pull
pm2 restart all
```

### Using cron with automatic shutdown

If you use a Raspberry Pi it is crucial to shutdown using

```bash
sudo poweroff
```

to avoid damaging the SD card (google for it to find more information). To perform this action after every workout
in a convenient way there is the run-script `raspberrypi.sh` which can be used.

*Details:* If the environment variable `SHUTDOWN_ONDISCONNECT=1` is set for the Zwifit process then Zwifit stops after
loosing the Wifi/Bluetooth connection what is usually caused by switching off the fitness machines. This situation is
detected by the run-script `raspberrypi.sh` to shutdown your Raspberry Pi properly.

Since the shutdown procedure requires `sudo` it is advisable to start the shell script using the root cron.
The run-script switches to the user `pi` for running Zwifit, so the root user is only used for shutdown.

To run Zwifit on startup edit the crontab by using

```bash
sudo crontab -e
```

and add this line at the end of the file:

```bash
@reboot nohup /home/pi/zwifit/raspberrypi.sh
```
(where you have to replace the path `/home/pi/zwifit` by the installation path of Zwifit at your system)

*Once applied steps for using the system are:*
1. Plug in your Raspberry Pi.
1. Wait until your fitness machines enlights the connection led (or the control page http://raspberrypi.local:1337 is available and the ifit symbol is green) which takes 70 seconds using a Raspberry Pi ZeroW.
1. Do your workouts with Zwift and connect or disconnect to the simulated fitness machine as often you need to.
1. Once you retire simple switch of your fitness machine.
1. About 10 seconds later it is save to plugin off your Raspberry Pi.

## Calibration

Zwifit will report your treadmill's exact speed, as measured by the machine itself. You can use the calibration
For treadmills, Zwifit will report your treadmill's exact speed, as measured by the machine itself. You can use the calibration
feature within Zwift to adjust this, just like you would with a footpod. Alternatively, load up the Zwifit Web UI
and head to the Settings page.

For indoor bikes, Zwifit will report your bikes exact power. Zwift will calculate speed based on your power.

## Control and Monitoring

The app runs a local web server that displays information from your treadmill, allows changing settings, and allows manual control of speed and incline. This can be used to change the speed and incline of your treadmill, too. To access this web site, you'll need to know the IP of your Pi, or the hostname, depending on your wireless router. For me, I can access it at http://raspberrypi.local:1337/ You may need to do the full IP, such as http://192.168.0.50:1337/ -- or if you're running this on a laptop, at http://localhost:1337/
The app runs a local web server that displays information from your fitness machine, allows changing settings, and allows manual control of speed and incline. This can be used to change the speed and incline of your fitness machine, too. To access this web site, you'll need to know the IP of your Pi, or the hostname, depending on your wireless router. For me, I can access it at http://raspberrypi.local:1337/ You may need to do the full IP, such as http://192.168.0.50:1337/ -- or if you're running this on a laptop, at http://localhost:1337/

If you have a monitor or touch screen connected to your Pi, you can run it in Kiosk mode. It can launch the Zwifit UI automatically. Follow the steps in this article to get started: https://pimylifeup.com/raspberry-pi-kiosk/

## Set the incline according to your current Zwift session

Zwift does not send the current gain of your running session to the treadmill. However, you can use the software [zwifit-incline-tracker](https://github.com/RasPelikan/zwifit-incline-tracker) to achieve this regardless. These automatic updates are only processed if the treadmill is in the active status.

For indoor bikes running Bluetooth, Zwift sends the gradient which will is passed onto the indoor bike via iFit Bluetooth. Note that Zwift has a slider setting for gradient, by default 50%. This means if your cycling at 4%, by default, your indoor bike will be asked to move to 2%. This slider setting at Max will make Zwift grade and indoor bike incline be equal.

## Contributing

Pull requests are welcome! Do your best to emulate the code around what you are editing.
Expand Down
20 changes: 16 additions & 4 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
#!/usr/bin/env node
let oneTime = require('./src/oneTimeSetup');
const settings = require('./src/settings');

oneTime.setup(() => {

let ifit = require('./src/ifit'),
api = require('./src/api'),
let api = require('./src/api'),
bluetooth = require('./src/bluetooth'),
onDeath = require('death');

/*
Initialization.
*/
api.start();
bluetooth.start();
ifit.connect();
let ifit = undefined;
if(settings.sim) {
ifit = require('./src/sim');
} else if (settings.ble) {
ifit = require('./src/ble/ifit');
} else {
ifit = require('./src/ifit');
}
if (process.env['SHUTDOWN_ONDISCONNECT']) {
ifit.connect(() => process.exit(99));
} else {
ifit.connect();
}
api.start(bluetooth, ifit);
onDeath(cleanUp);

/*
Expand Down
Loading