From cdb10cd2f05b0b9b036d755f4c04b97827407d41 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Wed, 15 Mar 2023 15:06:18 +0100 Subject: [PATCH 1/4] works! --- src/virtualbike.cpp | 79 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/src/virtualbike.cpp b/src/virtualbike.cpp index 11ab074c3..25eea8684 100644 --- a/src/virtualbike.cpp +++ b/src/virtualbike.cpp @@ -12,7 +12,6 @@ using namespace std::chrono_literals; virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHeartService, uint8_t bikeResistanceOffset, double bikeResistanceGain) { Bike = t; - this->noHeartService = noHeartService; this->bikeResistanceGain = bikeResistanceGain; this->bikeResistanceOffset = bikeResistanceOffset; @@ -91,7 +90,7 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear services << QBluetoothUuid::HeartRate; } - services << ((QBluetoothUuid::ServiceClassUuid)0xFF00); + // services << ((QBluetoothUuid::ServiceClassUuid)0xFF00); } else if (ifit) { services << (QBluetoothUuid(QStringLiteral("00001533-1412-efde-1523-785feabcd123"))); @@ -195,15 +194,56 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear serviceDataFIT.addCharacteristic(charDataFIT5); serviceDataFIT.addCharacteristic(charDataFIT6); } else if (power) { + QLowEnergyCharacteristicData charDataFIT; + charDataFIT.setUuid( + (QBluetoothUuid::CharacteristicType)0x2A00); // FitnessMachineFeatureCharacteristicUuid + 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); // FitnessMachineFeatureCharacteristicUuid + QByteArray valueFIT2; + valueFIT2.append((char)0x00); + charDataFIT2.setValue(valueFIT2); + charDataFIT2.setProperties(QLowEnergyCharacteristic::Read); + + serviceDataFIT.setUuid((QBluetoothUuid::ServiceClassUuid)0x1800); // FitnessMachineServiceUuid + serviceDataFIT.addCharacteristic(charDataFIT); + serviceDataFIT.addCharacteristic(charDataFIT2); + + QLowEnergyCharacteristicData charDataFIT3; + charDataFIT3.setUuid( + (QBluetoothUuid::CharacteristicType)0x2A05); // FitnessMachineFeatureCharacteristicUuid + charDataFIT3.setProperties(QLowEnergyCharacteristic::Indicate); + QByteArray descriptor33; + descriptor33.append((char)0x02); + descriptor33.append((char)0x00); + const QLowEnergyDescriptorData clientConfig43(QBluetoothUuid::ClientCharacteristicConfiguration, + descriptor33); + charDataFIT3.addDescriptor(clientConfig43); + + serviceEchelon.setUuid((QBluetoothUuid::ServiceClassUuid)0x1801); // FitnessMachineServiceUuid + serviceEchelon.addCharacteristic(charDataFIT3); QLowEnergyCharacteristicData charData; charData.setUuid(QBluetoothUuid::CharacteristicType::CyclingPowerFeature); charData.setProperties(QLowEnergyCharacteristic::Read); QByteArray value; - value.append((char)0x08); // crank supported - value.append((char)0x00); + value.append((char)0x00); // crank supported value.append((char)0x00); value.append((char)0x00); + value.append((char)0x08); charData.setValue(value); QLowEnergyCharacteristicData charData2; @@ -219,6 +259,7 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear QLowEnergyCharacteristicData charData3; charData3.setUuid(QBluetoothUuid::CharacteristicType::CyclingPowerMeasurement); charData3.setProperties(QLowEnergyCharacteristic::Notify | QLowEnergyCharacteristic::Read); + charData3.setValue(valueLocaltion); QByteArray descriptor; descriptor.append((char)0x01); descriptor.append((char)0x00); @@ -229,8 +270,8 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary); serviceData.setUuid(QBluetoothUuid::ServiceClassUuid::CyclingPower); serviceData.addCharacteristic(charData); - serviceData.addCharacteristic(charData3); serviceData.addCharacteristic(charData2); + serviceData.addCharacteristic(charData3); } else { QLowEnergyCharacteristicData charData; @@ -392,6 +433,8 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear serviceFIT = leController->addService(serviceDataFIT); } else { + serviceFIT = leController->addService(serviceDataFIT); + service = leController->addService(serviceEchelon); service = leController->addService(serviceData); } } @@ -433,10 +476,30 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear 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); + pars.setInterval(30, 50); + + QByteArray a; + a.append(0x02); + a.append(0x01); + a.append(0x06); + a.append(0x03); + a.append(0x03); + a.append(0x18); + a.append(0x18); + a.append(0x09); + a.append(0x09); + a.append(0x50); + a.append(0x69); + a.append(0x78); + a.append(0x65); + a.append(0x6c); + a.append(0x20); + a.append(0x36); + a.append(0x61); + + advertisingData.setRawData(a); + leController->startAdvertising(pars, advertisingData); //! [Start Advertising] } From 7cdf150ca6318524dd392147c69db7e38b2e7048 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Tue, 28 Mar 2023 14:43:18 +0200 Subject: [PATCH 2/4] added the garmin workaround also for the rsc sensor --- src/virtualtreadmill.cpp | 72 +++++++++++++++++++++++++++++++++++++--- src/virtualtreadmill.h | 4 +++ 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/virtualtreadmill.cpp b/src/virtualtreadmill.cpp index 616076842..c7e079830 100644 --- a/src/virtualtreadmill.cpp +++ b/src/virtualtreadmill.cpp @@ -67,8 +67,6 @@ virtualtreadmill::virtualtreadmill(bluetoothdevice *t, bool noHeartService) { services << QBluetoothUuid::HeartRate; } - services << ((QBluetoothUuid::ServiceClassUuid)0xFF00); - advertisingData.setServices(services); //! [Advertising Data] @@ -172,6 +170,45 @@ virtualtreadmill::virtualtreadmill(bluetoothdevice *t, bool noHeartService) { } if (RSCEnable()) { + QLowEnergyCharacteristicData charDataFIT; + charDataFIT.setUuid((QBluetoothUuid::CharacteristicType)0x2A00); // FitnessMachineFeatureCharacteristicUuid + 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); // FitnessMachineFeatureCharacteristicUuid + QByteArray valueFIT2; + valueFIT2.append((char)0x00); + charDataFIT2.setValue(valueFIT2); + charDataFIT2.setProperties(QLowEnergyCharacteristic::Read); + + serviceDataFIT.setUuid((QBluetoothUuid::ServiceClassUuid)0x1800); // FitnessMachineServiceUuid + serviceDataFIT.addCharacteristic(charDataFIT); + serviceDataFIT.addCharacteristic(charDataFIT2); + + QLowEnergyCharacteristicData charDataFIT3; + charDataFIT3.setUuid((QBluetoothUuid::CharacteristicType)0x2A05); // FitnessMachineFeatureCharacteristicUuid + charDataFIT3.setProperties(QLowEnergyCharacteristic::Indicate); + QByteArray descriptor33; + descriptor33.append((char)0x02); + descriptor33.append((char)0x00); + const QLowEnergyDescriptorData clientConfig43(QBluetoothUuid::ClientCharacteristicConfiguration, + descriptor33); + charDataFIT3.addDescriptor(clientConfig43); + + serviceEchelon.setUuid((QBluetoothUuid::ServiceClassUuid)0x1801); // FitnessMachineServiceUuid + serviceEchelon.addCharacteristic(charDataFIT3); + QLowEnergyCharacteristicData charData; charData.setUuid(QBluetoothUuid::CharacteristicType::RSCFeature); charData.setProperties(QLowEnergyCharacteristic::Read); @@ -234,8 +271,11 @@ virtualtreadmill::virtualtreadmill(bluetoothdevice *t, bool noHeartService) { Q_ASSERT(leController); if (ftmsServiceEnable()) serviceFTMS = leController->addService(serviceDataFTMS); - if (RSCEnable()) + if (RSCEnable()) { serviceRSC = leController->addService(serviceDataRSC); + serviceFIT = leController->addService(serviceDataFIT); + service = leController->addService(serviceEchelon); + } if (noHeartService == false) { serviceHR = leController->addService(serviceDataHR); } @@ -248,10 +288,32 @@ 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); + pars.setInterval(30, 50); + + QByteArray a; + a.append(0x02); + a.append(0x01); + a.append(0x06); + a.append(0x03); + a.append(0x03); + a.append(0x18); + a.append(0x18); + a.append(0x09); + a.append(0x09); + a.append(0x50); + a.append(0x69); + a.append(0x78); + a.append(0x65); + a.append(0x6c); + a.append(0x20); + a.append(0x36); + a.append(0x61); + + advertisingData.setRawData(a); + leController->startAdvertising(pars, advertisingData); + //! [Start Advertising] //! [Provide Heartbeat] diff --git a/src/virtualtreadmill.h b/src/virtualtreadmill.h index 7b1fbaeba..a20324af4 100644 --- a/src/virtualtreadmill.h +++ b/src/virtualtreadmill.h @@ -41,10 +41,14 @@ class virtualtreadmill : public QObject { QLowEnergyService *serviceFTMS = nullptr; QLowEnergyService *serviceRSC = nullptr; QLowEnergyService *serviceHR = nullptr; + QLowEnergyService *serviceFIT = nullptr; + QLowEnergyService *service = nullptr; QLowEnergyAdvertisingData advertisingData; QLowEnergyServiceData serviceDataFTMS; QLowEnergyServiceData serviceDataRSC; QLowEnergyServiceData serviceDataHR; + QLowEnergyServiceData serviceDataFIT; + QLowEnergyServiceData serviceEchelon; QTimer treadmillTimer; bluetoothdevice *treadMill; From 209194ce55d99bb6cb49d774a01a683600f71e4e Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Mon, 3 Apr 2023 10:28:27 +0200 Subject: [PATCH 3/4] fix on RSC --- src/virtualtreadmill.cpp | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/virtualtreadmill.cpp b/src/virtualtreadmill.cpp index c7e079830..ec6b86d02 100644 --- a/src/virtualtreadmill.cpp +++ b/src/virtualtreadmill.cpp @@ -292,26 +292,6 @@ virtualtreadmill::virtualtreadmill(bluetoothdevice *t, bool noHeartService) { pars.setInterval(30, 50); - QByteArray a; - a.append(0x02); - a.append(0x01); - a.append(0x06); - a.append(0x03); - a.append(0x03); - a.append(0x18); - a.append(0x18); - a.append(0x09); - a.append(0x09); - a.append(0x50); - a.append(0x69); - a.append(0x78); - a.append(0x65); - a.append(0x6c); - a.append(0x20); - a.append(0x36); - a.append(0x61); - - advertisingData.setRawData(a); leController->startAdvertising(pars, advertisingData); //! [Start Advertising] From 2fee48db839533954a9f45e56fbd4e798dc04dd2 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Wed, 12 Apr 2023 11:56:29 +0200 Subject: [PATCH 4/4] Update virtualtreadmill.cpp --- src/virtualtreadmill.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/virtualtreadmill.cpp b/src/virtualtreadmill.cpp index ec6b86d02..909fc014e 100644 --- a/src/virtualtreadmill.cpp +++ b/src/virtualtreadmill.cpp @@ -230,6 +230,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);