Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Peloton Treadmill Virtual Device on Raspberry #1915

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
65 changes: 60 additions & 5 deletions src/virtualtreadmill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ virtualtreadmill::virtualtreadmill(bluetoothdevice *t, bool noHeartService) {
services << QBluetoothUuid::HeartRate;
}

services << ((QBluetoothUuid::ServiceClassUuid)0xFF00);

advertisingData.setServices(services);
//! [Advertising Data]

Expand Down Expand Up @@ -169,6 +167,48 @@ virtualtreadmill::virtualtreadmill(bluetoothdevice *t, bool noHeartService) {
serviceDataFTMS.addCharacteristic(charDataFIT2);
}

#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
qDebug() << "Raspberry workaround for sending metrics to the peloton app";
QLowEnergyCharacteristicData charDataFIT;
charDataFIT.setUuid((QBluetoothUuid::CharacteristicType)0x2A00);
QByteArray valueFIT;
valueFIT.append((char)'P'); // average speed, cadence and resistance level supported
valueFIT.append((char)'i'); // heart rate and elapsed time
valueFIT.append((char)'x');
valueFIT.append((char)'e');
valueFIT.append((char)'l'); // resistance and power target supported
valueFIT.append((char)' '); // indoor simulation, wheel and spin down supported
valueFIT.append((char)'6');
valueFIT.append((char)'a');
valueFIT.append((char)0x00);
charDataFIT.setValue(valueFIT);
charDataFIT.setProperties(QLowEnergyCharacteristic::Read);

QLowEnergyCharacteristicData charDataFIT2;
charDataFIT2.setUuid((QBluetoothUuid::CharacteristicType)0x2A01);
QByteArray valueFIT2;
valueFIT2.append((char)0x00);
charDataFIT2.setValue(valueFIT2);
charDataFIT2.setProperties(QLowEnergyCharacteristic::Read);

genericAccessServerData.setUuid((QBluetoothUuid::ServiceClassUuid)0x1800);
genericAccessServerData.addCharacteristic(charDataFIT);
genericAccessServerData.addCharacteristic(charDataFIT2);

QLowEnergyCharacteristicData charDataFIT3;
charDataFIT3.setUuid((QBluetoothUuid::CharacteristicType)0x2A05);
charDataFIT3.setProperties(QLowEnergyCharacteristic::Indicate);
QByteArray descriptor33;
descriptor33.append((char)0x02);
descriptor33.append((char)0x00);
const QLowEnergyDescriptorData clientConfig43(QBluetoothUuid::ClientCharacteristicConfiguration,
descriptor33);
charDataFIT3.addDescriptor(clientConfig43);

genericAttributeServiceData.setUuid((QBluetoothUuid::ServiceClassUuid)0x1801);
genericAttributeServiceData.addCharacteristic(charDataFIT3);
#endif

if (RSCEnable()) {
QLowEnergyCharacteristicData charData;
charData.setUuid(QBluetoothUuid::CharacteristicType::RSCFeature);
Expand All @@ -191,6 +231,7 @@ virtualtreadmill::virtualtreadmill(bluetoothdevice *t, bool noHeartService) {
QLowEnergyCharacteristicData charData3;
charData3.setUuid(QBluetoothUuid::CharacteristicType::RSCMeasurement);
charData3.setProperties(QLowEnergyCharacteristic::Read | QLowEnergyCharacteristic::Notify);
charData3.setValue(valueLocaltion);
QByteArray descriptor;
descriptor.append((char)0x01);
descriptor.append((char)0x00);
Expand Down Expand Up @@ -232,8 +273,14 @@ virtualtreadmill::virtualtreadmill(bluetoothdevice *t, bool noHeartService) {
Q_ASSERT(leController);
if (ftmsServiceEnable())
serviceFTMS = leController->addService(serviceDataFTMS);
if (RSCEnable())
if (RSCEnable()) {
serviceRSC = leController->addService(serviceDataRSC);
}
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
genericAccessServer = leController->addService(genericAccessServerData);
genericAttributeService = leController->addService(genericAttributeServiceData);
#endif

if (noHeartService == false) {
serviceHR = leController->addService(serviceDataHR);
}
Expand All @@ -246,10 +293,13 @@ virtualtreadmill::virtualtreadmill(bluetoothdevice *t, bool noHeartService) {
settings.value(QZSettings::bluetooth_relaxed, QZSettings::default_bluetooth_relaxed).toBool();
QLowEnergyAdvertisingParameters pars = QLowEnergyAdvertisingParameters();
if (!bluetooth_relaxed) {
pars.setInterval(100, 100);
}

leController->startAdvertising(pars, advertisingData, advertisingData);
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
pars.setInterval(30, 50);
leController->startAdvertising(pars, advertisingData);
#endif

//! [Start Advertising]

//! [Provide Heartbeat]
Expand Down Expand Up @@ -318,6 +368,11 @@ void virtualtreadmill::reconnect() {
if (RSCEnable())
serviceRSC = leController->addService(serviceDataRSC);

#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
genericAccessServer = leController->addService(genericAccessServerData);
genericAttributeService = leController->addService(genericAttributeServiceData);
#endif

if (noHeartService == false) {
serviceHR = leController->addService(serviceDataHR);
}
Expand Down
8 changes: 8 additions & 0 deletions src/virtualtreadmill.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,18 @@ class virtualtreadmill : public virtualdevice {
QLowEnergyService *serviceFTMS = nullptr;
QLowEnergyService *serviceRSC = nullptr;
QLowEnergyService *serviceHR = nullptr;
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
QLowEnergyService *genericAccessServer = nullptr;
QLowEnergyService *genericAttributeService = nullptr;
#endif
QLowEnergyAdvertisingData advertisingData;
QLowEnergyServiceData serviceDataFTMS;
QLowEnergyServiceData serviceDataRSC;
QLowEnergyServiceData serviceDataHR;
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
QLowEnergyServiceData genericAccessServerData;
QLowEnergyServiceData genericAttributeServiceData;
#endif
QTimer treadmillTimer;
bluetoothdevice *treadMill;

Expand Down
Loading