Skip to content

Commit

Permalink
Merge pull request #498 from doudar/VirtualShiftingPassthrough
Browse files Browse the repository at this point in the history
Virtual shifting passthrough
  • Loading branch information
doudar authored Dec 21, 2023
2 parents 53dbfa7 + 4cd1052 commit 7f2484e
Show file tree
Hide file tree
Showing 21 changed files with 627 additions and 413 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added

- Added pass through shifting in both ERG and SIM mode.
### Changed
- Updated communications overview picture.
- Updated kit purchasing links.
- MIN_ERG_CADENCE created and changed from 20 to 30.
- Fixed DNS server in AP mode.
- Fixed an issue with IC4 and variants not displaying device name in Bluetooth scanner. Fixes #500
- Switched from using Power Table to a Torque Table for better compensation in cad variations.
- added test for invalid Peloton data to keep stepper from running away without resistance information.

### Hardware
- Wire diameter reduced from 7.2mm to 6.0mm on the window passthrough to accommodate the latest batch of cables.
Expand Down
Binary file not shown.
Binary file not shown.
Binary file added Hardware/Common Assets/Inserts/YOSUDA_PRO.STL
Binary file not shown.
172 changes: 7 additions & 165 deletions include/BLE_Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
#include <memory>
#include <NimBLEDevice.h>
#include <Arduino.h>
#include <Main.h>
#include "Main.h"
#include "BLE_Definitions.h"

#define BLE_CLIENT_LOG_TAG "BLE_Client"
#define BLE_COMMON_LOG_TAG "BLE_Common"
Expand Down Expand Up @@ -167,6 +168,8 @@ class SpinBLEAdvertisedDevice {
};

class SpinBLEClient {
private:

public: // Not all of these need to be public. This should be cleaned up
// later.
boolean connectedPM = false;
Expand Down Expand Up @@ -194,9 +197,9 @@ class SpinBLEClient {
// Check for duplicate services of BLEClient and remove the previously
// connected one.
void removeDuplicates(NimBLEClient *pClient);
void resetDevices(NimBLEClient *pclient);
void resetDevices(NimBLEClient *pClient);
void postConnect();
void FTMSControlPointWrite(const uint8_t *pData, int length);
void FTMSControlPointWrite(const uint8_t* pData, int length);
void connectBLE_HID(NimBLEClient *pClient);
void keepAliveBLE_HID(NimBLEClient *pClient);
void checkBLEReconnect();
Expand All @@ -217,165 +220,4 @@ class MyClientCallback : public NimBLEClientCallbacks {
void onAuthenticationComplete(ble_gap_conn_desc);
};

extern SpinBLEClient spinBLEClient;

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.13: Training Status Field Definition
struct FitnessMachineTrainingStatus {
enum Types : uint8_t {
Other = 0x00,
Idle = 0x01,
WarmingUp = 0x02,
LowIntensityInterval = 0x03,
HighIntensityInterval = 0x04,
RecoveryInterval = 0x05,
Isometric = 0x06,
HeartRateControl = 0x07,
FitnessTest = 0x08,
SpeedOutsideOfControlRegionLow = 0x09,
SpeedOutsideOfControlRegionHigh = 0x0A,
CoolDown = 0x0B,
WattControl = 0x0C,
ManualMode = 0x0D,
PreWorkout = 0x0E,
PostWorkout = 0x0F,
// Reserved for Future Use 0x10-0xFF
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.24: Fitness Machine Control Point characteristic – Result Codes
struct FitnessMachineControlPointResultCode {
enum Types : uint8_t {
ReservedForFutureUse = 0x00,
Success = 0x01,
OpCodeNotSupported = 0x02,
InvalidParameter = 0x03,
OperationFailed = 0x04,
ControlNotPermitted = 0x05,
// Reserved for Future Use = 0x06-0xFF
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.3: Definition of the bits of the Fitness Machine Features field
struct FitnessMachineFeatureFlags {
enum Types : uint {
AverageSpeedSupported = 1U << 0,
CadenceSupported = 1U << 1,
TotalDistanceSupported = 1U << 2,
InclinationSupported = 1U << 3,
ElevationGainSupported = 1U << 4,
PaceSupported = 1U << 5,
StepCountSupported = 1U << 6,
ResistanceLevelSupported = 1U << 7,
StrideCountSupported = 1U << 8,
ExpendedEnergySupported = 1U << 9,
HeartRateMeasurementSupported = 1U << 10,
MetabolicEquivalentSupported = 1U << 11,
ElapsedTimeSupported = 1U << 12,
RemainingTimeSupported = 1U << 13,
PowerMeasurementSupported = 1U << 14,
ForceOnBeltAndPowerOutputSupported = 1U << 15,
UserDataRetentionSupported = 1U << 16
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.4: Definition of the bits of the Target Setting Features field
struct FitnessMachineTargetFlags {
enum Types : uint {
SpeedTargetSettingSupported = 1U << 0,
InclinationTargetSettingSupported = 1U << 1,
ResistanceTargetSettingSupported = 1U << 2,
PowerTargetSettingSupported = 1U << 3,
HeartRateTargetSettingSupported = 1U << 4,
TargetedExpendedEnergyConfigurationSupported = 1U << 5,
TargetedStepNumberConfigurationSupported = 1U << 6,
TargetedStrideNumberConfigurationSupported = 1U << 7,
TargetedDistanceConfigurationSupported = 1U << 8,
TargetedTrainingTimeConfigurationSupported = 1U << 9,
TargetedTimeTwoHeartRateZonesConfigurationSupported = 1U << 10,
TargetedTimeThreeHeartRateZonesConfigurationSupported = 1U << 11,
TargetedTimeFiveHeartRateZonesConfigurationSupported = 1U << 12,
IndoorBikeSimulationParametersSupported = 1U << 13,
WheelCircumferenceConfigurationSupported = 1U << 14,
SpinDownControlSupported = 1U << 15,
TargetedCadenceConfigurationSupported = 1U << 16
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.16.1: Fitness Machine Control Point Procedure Requirements
struct FitnessMachineControlPointProcedure {
enum Types : uint8_t {
RequestControl = 0x00,
Reset = 0x01,
SetTargetSpeed = 0x02,
SetTargetInclination = 0x03,
SetTargetResistanceLevel = 0x04,
SetTargetPower = 0x05,
SetTargetHeartRate = 0x06,
StartOrResume = 0x07,
StopOrPause = 0x08,
SetIndoorBikeSimulationParameters = 0x11,
SetWheelCircumference = 0x12,
SpinDownControl = 0x13,
SetTargetedCadence = 0x14,
// Reserved for Future Use 0x15-0x7F
ResponseCode = 0x80
// Reserved for Future Use 0x81-0xFF
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.17: Fitness Machine Status
struct FitnessMachineStatus {
enum Types : uint {
ReservedForFutureUse = 0x00,
Reset = 0x01,
StoppedOrPausedByUser = 0x02,
StoppedOrPausedBySafetyKey = 0x03,
StartedOrResumedByUser = 0x04,
TargetSpeedChanged = 0x05,
TargetInclineChanged = 0x06,
TargetResistanceLevelChanged = 0x07,
TargetPowerChanged = 0x08,
TargetHeartRateChanged = 0x09,
IndoorBikeSimulationParametersChanged = 0x12,
WheelCircumferenceChanged = 0x13,
SpinDownStatus = 0x14,
TargetedCadenceChanged = 0x15,
// Reserved for Future Use 0x16-0xFE
ControlPermissionLost = 0xFF
};
};

inline FitnessMachineFeatureFlags::Types operator|(FitnessMachineFeatureFlags::Types a, FitnessMachineFeatureFlags::Types b) {
return static_cast<FitnessMachineFeatureFlags::Types>(static_cast<int>(a) | static_cast<int>(b));
}

inline FitnessMachineTargetFlags::Types operator|(FitnessMachineTargetFlags::Types a, FitnessMachineTargetFlags::Types b) {
return static_cast<FitnessMachineTargetFlags::Types>(static_cast<int>(a) | static_cast<int>(b));
}

struct FitnessMachineFeature {
union {
struct {
union {
enum FitnessMachineFeatureFlags::Types featureFlags;
uint8_t bytes[4];
} featureFlags;
union {
enum FitnessMachineTargetFlags::Types targetFlags;
uint8_t bytes[4];
} targetFlags;
};
uint8_t bytes[8];
};
};

struct FtmsStatus {
uint8_t data[8];
int length;
};
extern SpinBLEClient spinBLEClient;
169 changes: 169 additions & 0 deletions include/BLE_Definitions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* Copyright (C) 2020 Anthony Doud & Joel Baranick
* All rights reserved
*
* SPDX-License-Identifier: GPL-2.0-only
*/

#pragma once

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.13: Training Status Field Definition
struct FitnessMachineTrainingStatus {
enum Types : uint8_t {
Other = 0x00,
Idle = 0x01,
WarmingUp = 0x02,
LowIntensityInterval = 0x03,
HighIntensityInterval = 0x04,
RecoveryInterval = 0x05,
Isometric = 0x06,
HeartRateControl = 0x07,
FitnessTest = 0x08,
SpeedOutsideOfControlRegionLow = 0x09,
SpeedOutsideOfControlRegionHigh = 0x0A,
CoolDown = 0x0B,
WattControl = 0x0C,
ManualMode = 0x0D,
PreWorkout = 0x0E,
PostWorkout = 0x0F,
// Reserved for Future Use 0x10-0xFF
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.24: Fitness Machine Control Point characteristic – Result Codes
struct FitnessMachineControlPointResultCode {
enum Types : uint8_t {
ReservedForFutureUse = 0x00,
Success = 0x01,
OpCodeNotSupported = 0x02,
InvalidParameter = 0x03,
OperationFailed = 0x04,
ControlNotPermitted = 0x05,
// Reserved for Future Use = 0x06-0xFF
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.3: Definition of the bits of the Fitness Machine Features field
struct FitnessMachineFeatureFlags {
enum Types : uint {
AverageSpeedSupported = 1U << 0,
CadenceSupported = 1U << 1,
TotalDistanceSupported = 1U << 2,
InclinationSupported = 1U << 3,
ElevationGainSupported = 1U << 4,
PaceSupported = 1U << 5,
StepCountSupported = 1U << 6,
ResistanceLevelSupported = 1U << 7,
StrideCountSupported = 1U << 8,
ExpendedEnergySupported = 1U << 9,
HeartRateMeasurementSupported = 1U << 10,
MetabolicEquivalentSupported = 1U << 11,
ElapsedTimeSupported = 1U << 12,
RemainingTimeSupported = 1U << 13,
PowerMeasurementSupported = 1U << 14,
ForceOnBeltAndPowerOutputSupported = 1U << 15,
UserDataRetentionSupported = 1U << 16
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.4: Definition of the bits of the Target Setting Features field
struct FitnessMachineTargetFlags {
enum Types : uint {
SpeedTargetSettingSupported = 1U << 0,
InclinationTargetSettingSupported = 1U << 1,
ResistanceTargetSettingSupported = 1U << 2,
PowerTargetSettingSupported = 1U << 3,
HeartRateTargetSettingSupported = 1U << 4,
TargetedExpendedEnergyConfigurationSupported = 1U << 5,
TargetedStepNumberConfigurationSupported = 1U << 6,
TargetedStrideNumberConfigurationSupported = 1U << 7,
TargetedDistanceConfigurationSupported = 1U << 8,
TargetedTrainingTimeConfigurationSupported = 1U << 9,
TargetedTimeTwoHeartRateZonesConfigurationSupported = 1U << 10,
TargetedTimeThreeHeartRateZonesConfigurationSupported = 1U << 11,
TargetedTimeFiveHeartRateZonesConfigurationSupported = 1U << 12,
IndoorBikeSimulationParametersSupported = 1U << 13,
WheelCircumferenceConfigurationSupported = 1U << 14,
SpinDownControlSupported = 1U << 15,
TargetedCadenceConfigurationSupported = 1U << 16
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.16.1: Fitness Machine Control Point Procedure Requirements
struct FitnessMachineControlPointProcedure {
enum Types : uint8_t {
RequestControl = 0x00,
Reset = 0x01,
SetTargetSpeed = 0x02,
SetTargetInclination = 0x03,
SetTargetResistanceLevel = 0x04,
SetTargetPower = 0x05,
SetTargetHeartRate = 0x06,
StartOrResume = 0x07,
StopOrPause = 0x08,
SetIndoorBikeSimulationParameters = 0x11,
SetWheelCircumference = 0x12,
SpinDownControl = 0x13,
SetTargetedCadence = 0x14,
// Reserved for Future Use 0x15-0x7F
ResponseCode = 0x80
// Reserved for Future Use 0x81-0xFF
};
};

// https://www.bluetooth.com/specifications/specs/fitness-machine-service-1-0/
// Table 4.17: Fitness Machine Status
struct FitnessMachineStatus {
enum Types : uint {
ReservedForFutureUse = 0x00,
Reset = 0x01,
StoppedOrPausedByUser = 0x02,
StoppedOrPausedBySafetyKey = 0x03,
StartedOrResumedByUser = 0x04,
TargetSpeedChanged = 0x05,
TargetInclineChanged = 0x06,
TargetResistanceLevelChanged = 0x07,
TargetPowerChanged = 0x08,
TargetHeartRateChanged = 0x09,
IndoorBikeSimulationParametersChanged = 0x12,
WheelCircumferenceChanged = 0x13,
SpinDownStatus = 0x14,
TargetedCadenceChanged = 0x15,
// Reserved for Future Use 0x16-0xFE
ControlPermissionLost = 0xFF
};
};

inline FitnessMachineFeatureFlags::Types operator|(FitnessMachineFeatureFlags::Types a, FitnessMachineFeatureFlags::Types b) {
return static_cast<FitnessMachineFeatureFlags::Types>(static_cast<int>(a) | static_cast<int>(b));
}

inline FitnessMachineTargetFlags::Types operator|(FitnessMachineTargetFlags::Types a, FitnessMachineTargetFlags::Types b) {
return static_cast<FitnessMachineTargetFlags::Types>(static_cast<int>(a) | static_cast<int>(b));
}

struct FitnessMachineFeature {
union {
struct {
union {
enum FitnessMachineFeatureFlags::Types featureFlags;
uint8_t bytes[4];
} featureFlags;
union {
enum FitnessMachineTargetFlags::Types targetFlags;
uint8_t bytes[4];
} targetFlags;
};
uint8_t bytes[8];
};
};

struct FtmsStatus {
uint8_t data[8];
int length;
};
Loading

0 comments on commit 7f2484e

Please sign in to comment.