Skip to content

Commit

Permalink
Add workaround for Flywheel bike power dropout.
Browse files Browse the repository at this point in the history
The Flywheel bike occasionally reports spurious zero watts power values.
The underlying cause is unknown but it seems to occur once every few
minutes. This can be annoying if you are cycling at high effort and
suddenly see your power drop to zero. A simple but effective fix is to
just repeat the previous non-zero power value whenever the current power
is zero and current cadence is greater than zero. The accepted tradeoff
is that a legitimate gradual slow down to zero watts may take an extra
second to arrive at zero watts.
  • Loading branch information
ptx2 committed Aug 20, 2020
1 parent c913e0e commit 8f19542
Showing 1 changed file with 37 additions and 1 deletion.
38 changes: 37 additions & 1 deletion src/bikes/flywheel.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const LE_MAX_INTERVAL = 60*1.25;
const LE_LATENCY = 0;
const LE_SUPERVISION_TIMEOUT = 4000;

const debuglog = util.debuglog('flywheel');

/**
* Handles communication with Flywheel indoor training bike using the bike's
* proprietary protocol atop a standard Bluetooth LE GATT Nordic UART Service.
Expand Down Expand Up @@ -50,6 +52,8 @@ export class FlywheelBikeClient extends EventEmitter {
throw new Error('Already connected');
}

this.fixPowerDropout = createPowerDropoutFilter();

// scan
const peripheral = await scan(this.noble, [UART_SERVICE_UUID], this.filters);

Expand Down Expand Up @@ -102,7 +106,11 @@ export class FlywheelBikeClient extends EventEmitter {
try {
const {type, payload} = parse(data);
if (type === 'stats') {
this.emit(type, payload);
const fixed = this.fixPowerDropout(payload);
if (fixed.power !== payload.power) {
debuglog(`*** replaced zero power with previous power ${fixed.power}`);
}
this.emit(type, fixed);
}
} catch (e) {
if (!/unable to parse message/.test(e)) {
Expand Down Expand Up @@ -206,3 +214,31 @@ async function updateConnectionParameters(peripheral, minInterval, maxInterval,
await execFileAsync(cmd, args);
}
}

/**
* Workaround for an issue in the Flywheel Bike where it occasionally
* incorrectly reports zero power (watts).
*
* @private
*/
function createPowerDropoutFilter() {
let prev = null;

/**
* Returns stats payload with spurious zero removed.
* @param {object} curr - current stats payload
* @param {number} curr.power - power (watts)
* @param {number} curr.cadence - cadence (rpm)
* @returns {object} fixed - fixed stats payload
* @returns {object} fixed.power - fixed power (watts)
* @returns {object} fixed.cadence - cadence
*/
return function (curr) {
let fixed = {...curr};
if (prev !== null && curr.power === 0 && curr.cadence > 0 && prev.power > 0) {
fixed.power = prev.power;
}
prev = curr;
return fixed;
}
}

0 comments on commit 8f19542

Please sign in to comment.