From 86750047ea9bb6eecc96ad4af1949ffc78fa8274 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Thu, 16 May 2024 17:44:54 +0200 Subject: [PATCH 01/13] let's see if the tacx app gets QZ --- src/qzsettings.cpp | 4 +++- src/qzsettings.h | 3 +++ src/settings.qml | 28 ++++++++++++++++++++++++++++ src/virtualdevices/virtualbike.cpp | 9 +++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/qzsettings.cpp b/src/qzsettings.cpp index dd0e5ef73..9539c0da3 100644 --- a/src/qzsettings.cpp +++ b/src/qzsettings.cpp @@ -738,8 +738,9 @@ const QString QZSettings::default_treadmillDataPoints = QStringLiteral(""); const QString QZSettings::nordictrack_s20i_treadmill = QStringLiteral("nordictrack_s20i_treadmill"); const QString QZSettings::proform_595i_proshox2 = QStringLiteral("proform_595i_proshox2"); const QString QZSettings::proform_treadmill_8_7 = QStringLiteral("proform_treadmill_8_7"); +const QString QZSettings::virtual_device_tacx = QStringLiteral("virtual_device_tacx"); -const uint32_t allSettingsCount = 623; +const uint32_t allSettingsCount = 624; QVariant allSettings[allSettingsCount][2] = { {QZSettings::cryptoKeySettingsProfiles, QZSettings::default_cryptoKeySettingsProfiles}, @@ -1369,6 +1370,7 @@ QVariant allSettings[allSettingsCount][2] = { {QZSettings::nordictrack_s20i_treadmill, QZSettings::default_nordictrack_s20i_treadmill}, {QZSettings::proform_595i_proshox2, QZSettings::default_proform_595i_proshox2}, {QZSettings::proform_treadmill_8_7, QZSettings::default_proform_treadmill_8_7}, + {QZSettings::virtual_device_tacx, QZSettings::default_virtual_device_tacx}, }; void QZSettings::qDebugAllSettings(bool showDefaults) { diff --git a/src/qzsettings.h b/src/qzsettings.h index 038b78e7d..36318fe13 100644 --- a/src/qzsettings.h +++ b/src/qzsettings.h @@ -2069,6 +2069,9 @@ class QZSettings { static const QString proform_treadmill_8_7; static constexpr bool default_proform_treadmill_8_7 = false; + static const QString virtual_device_tacx; + static constexpr bool default_virtual_device_tacx = false; + /** * @brief Write the QSettings values using the constants from this namespace. * @param showDefaults Optionally indicates if the default should be shown with the key. diff --git a/src/settings.qml b/src/settings.qml index 205010dc8..c70b0902b 100644 --- a/src/settings.qml +++ b/src/settings.qml @@ -939,6 +939,7 @@ import QtQuick.Dialogs 1.0 // from version 2.16.55 property bool proform_treadmill_8_7: false + property bool virtual_device_tacx: false } function paddingZeros(text, limit) { @@ -9673,6 +9674,33 @@ import QtQuick.Dialogs 1.0 Layout.fillWidth: true color: Material.color(Material.Lime) } + + SwitchDelegate { + text: qsTr("Virtual Tacx") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.virtual_device_tacx + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.virtual_device_tacx = checked; window.settings_restart_to_apply = true; } + } + + Label { + text: qsTr("Enables a virtual bluetooth bridge to the Tacx App.") + font.bold: true + font.italic: true + font.pixelSize: 9 + textFormat: Text.PlainText + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + color: Material.color(Material.Lime) + } } } AccordionCheckElement { diff --git a/src/virtualdevices/virtualbike.cpp b/src/virtualdevices/virtualbike.cpp index f0a7ab793..06f3ee391 100644 --- a/src/virtualdevices/virtualbike.cpp +++ b/src/virtualdevices/virtualbike.cpp @@ -29,6 +29,10 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear settings.value(QZSettings::virtual_device_echelon, QZSettings::default_virtual_device_echelon).toBool(); bool ifit = settings.value(QZSettings::virtual_device_ifit, QZSettings::default_virtual_device_ifit).toBool(); bool garmin_bluetooth_compatibility = settings.value(QZSettings::garmin_bluetooth_compatibility, QZSettings::default_garmin_bluetooth_compatibility).toBool(); + bool virtual_device_tacx = settings.value(QZSettings::virtual_device_tacx, QZSettings::default_virtual_device_tacx).toBool(); + + if(virtual_device_tacx) + power = true; if (settings.value(QZSettings::dircon_yes, QZSettings::default_dircon_yes).toBool()) { dirconManager = new DirconManager(Bike, bikeResistanceOffset, bikeResistanceGain, this); @@ -85,6 +89,11 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear else if (power) { services << (QBluetoothUuid::ServiceClassUuid::CyclingPower); + + if(virtual_device_tacx) { + services << (QBluetoothUuid(QStringLiteral("6E40FEC1-B5A3-F393-E0A9-E50E24DCCA9E"))); + } + } else { services << (QBluetoothUuid::ServiceClassUuid::CyclingSpeedAndCadence); } From 811b85ec45dcbe11b2735ce3d8a2e08bf307029b Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Fri, 17 May 2024 13:09:03 +0800 Subject: [PATCH 02/13] Update virtualbike.cpp --- src/virtualdevices/virtualbike.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/virtualdevices/virtualbike.cpp b/src/virtualdevices/virtualbike.cpp index 06f3ee391..c6f2049b4 100644 --- a/src/virtualdevices/virtualbike.cpp +++ b/src/virtualdevices/virtualbike.cpp @@ -101,8 +101,6 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear if (!this->noHeartService || heart_only) { services << QBluetoothUuid::HeartRate; } - - services << ((QBluetoothUuid::ServiceClassUuid)0xFF00); } else if (ifit) { services << (QBluetoothUuid(QStringLiteral("00001533-1412-efde-1523-785feabcd123"))); From 5e219c34c15ac1ee1f87c96ff049d7a961f98854 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Sat, 18 May 2024 17:13:09 +0200 Subject: [PATCH 03/13] not found from ios --- src/virtualdevices/virtualbike.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/virtualdevices/virtualbike.cpp b/src/virtualdevices/virtualbike.cpp index c6f2049b4..045c4d2ae 100644 --- a/src/virtualdevices/virtualbike.cpp +++ b/src/virtualdevices/virtualbike.cpp @@ -58,7 +58,7 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear #ifndef IO_UNDER_QT bool ios_peloton_workaround = settings.value(QZSettings::ios_peloton_workaround, QZSettings::default_ios_peloton_workaround).toBool(); - if ((ios_peloton_workaround && !cadence && !echelon && !ifit && !heart_only) || garmin_bluetooth_compatibility) { + if ((ios_peloton_workaround && !cadence && !echelon && !ifit && !heart_only && !virtual_device_tacx) || garmin_bluetooth_compatibility) { qDebug() << "ios_zwift_workaround activated!"; h = new lockscreen(); @@ -72,7 +72,9 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear //! [Advertising Data] advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral); advertisingData.setIncludePowerLevel(true); - if (!echelon && !ifit) { + if(virtual_device_tacx) { + advertisingData.setLocalName(QStringLiteral("TACX SMART BIKE")); + } else if (!echelon && !ifit) { advertisingData.setLocalName(QStringLiteral("DomyosBridge")); } else if (ifit) { advertisingData.setLocalName(QStringLiteral("I_EB")); @@ -87,13 +89,13 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear services << ((QBluetoothUuid::ServiceClassUuid)0x1826); } // FitnessMachineServiceUuid else if (power) { - - services << (QBluetoothUuid::ServiceClassUuid::CyclingPower); - if(virtual_device_tacx) { services << (QBluetoothUuid(QStringLiteral("6E40FEC1-B5A3-F393-E0A9-E50E24DCCA9E"))); } + services << (QBluetoothUuid::ServiceClassUuid::CyclingPower); + + } else { services << (QBluetoothUuid::ServiceClassUuid::CyclingSpeedAndCadence); } From 0ee0b056a4c01cb349a16633ace6a3ce9a011a76 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Tue, 28 May 2024 08:46:01 +0200 Subject: [PATCH 04/13] adding also the cadence service --- src/virtualdevices/virtualbike.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/virtualdevices/virtualbike.cpp b/src/virtualdevices/virtualbike.cpp index 045c4d2ae..f3fa5c936 100644 --- a/src/virtualdevices/virtualbike.cpp +++ b/src/virtualdevices/virtualbike.cpp @@ -89,13 +89,12 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear services << ((QBluetoothUuid::ServiceClassUuid)0x1826); } // FitnessMachineServiceUuid else if (power) { - if(virtual_device_tacx) { - services << (QBluetoothUuid(QStringLiteral("6E40FEC1-B5A3-F393-E0A9-E50E24DCCA9E"))); - } - services << (QBluetoothUuid::ServiceClassUuid::CyclingPower); - + if(virtual_device_tacx) { + services << (QBluetoothUuid::ServiceClassUuid::CyclingSpeedAndCadence); + services << (QBluetoothUuid(QStringLiteral("6e40fec1-b5a3-f393-e0a9-e50e24dcca9e"))); + } } else { services << (QBluetoothUuid::ServiceClassUuid::CyclingSpeedAndCadence); } From 445bc52dd763499de0594224c5909ec982de3d24 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Tue, 28 May 2024 10:11:31 +0200 Subject: [PATCH 05/13] nothing works --- src/ios/BLEPeripheralManager.swift | 2 ++ src/ios/lockscreen.h | 2 +- src/ios/lockscreen.mm | 4 ++-- src/ios/virtualbike_zwift.swift | 12 +++++++++--- src/virtualdevices/virtualbike.cpp | 4 ++-- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/ios/BLEPeripheralManager.swift b/src/ios/BLEPeripheralManager.swift index bd3d438e5..84df4cb7c 100644 --- a/src/ios/BLEPeripheralManager.swift +++ b/src/ios/BLEPeripheralManager.swift @@ -16,6 +16,8 @@ import CoreBluetooth let heartRateServiceUUID = CBUUID(string: "0x180D") let heartRateCharacteristicUUID = CBUUID(string: "0x2A37") +let TACXServiceUUID = CBUUID(string: "6E40FEC1-B5A3-F393-E0A9-E50E24DCCA9E") + let CSCServiceUUID = CBUUID(string: "0x1816") let CSCFeatureCharacteristicUUID = CBUUID(string: "0x2A5C") let SensorLocationCharacteristicUUID = CBUUID(string: "0x2A5D") diff --git a/src/ios/lockscreen.h b/src/ios/lockscreen.h index c8dc15e83..e15bc6764 100644 --- a/src/ios/lockscreen.h +++ b/src/ios/lockscreen.h @@ -18,7 +18,7 @@ class lockscreen { void virtualbike_setHeartRate(unsigned char heartRate); void virtualbike_setCadence(unsigned short crankRevolutions, unsigned short lastCrankEventTime); - void virtualbike_zwift_ios(bool disable_hr, bool garmin_bluetooth_compatibility); + void virtualbike_zwift_ios(bool disable_hr, bool garmin_bluetooth_compatibility, bool tacx); double virtualbike_getCurrentSlope(); double virtualbike_getCurrentCRR(); double virtualbike_getCurrentCW(); diff --git a/src/ios/lockscreen.mm b/src/ios/lockscreen.mm index 9120f2a29..f60819839 100644 --- a/src/ios/lockscreen.mm +++ b/src/ios/lockscreen.mm @@ -101,9 +101,9 @@ [_virtualbike updateCadenceWithCrankRevolutions:crankRevolutions LastCrankEventTime:lastCrankEventTime]; } -void lockscreen::virtualbike_zwift_ios(bool disable_hr, bool garmin_bluetooth_compatibility) +void lockscreen::virtualbike_zwift_ios(bool disable_hr, bool garmin_bluetooth_compatibility, bool tacx) { - _virtualbike_zwift = [[virtualbike_zwift alloc] initWithDisable_hr:disable_hr garmin_bluetooth_compatibility:garmin_bluetooth_compatibility]; + _virtualbike_zwift = [[virtualbike_zwift alloc] initWithDisable_hr:disable_hr garmin_bluetooth_compatibility:garmin_bluetooth_compatibility tacx:tacx]; } void lockscreen::virtualrower_ios() diff --git a/src/ios/virtualbike_zwift.swift b/src/ios/virtualbike_zwift.swift index 7315efdc6..1963dff19 100644 --- a/src/ios/virtualbike_zwift.swift +++ b/src/ios/virtualbike_zwift.swift @@ -11,9 +11,9 @@ let TrainingStatusUuid = CBUUID(string: "0x2AD3"); @objc public class virtualbike_zwift: NSObject { private var peripheralManager: BLEPeripheralManagerZwift! - @objc public init(disable_hr: Bool, garmin_bluetooth_compatibility: Bool) { + @objc public init(disable_hr: Bool, garmin_bluetooth_compatibility: Bool, tacx: Bool) { super.init() - peripheralManager = BLEPeripheralManagerZwift(disable_hr: disable_hr, garmin_bluetooth_compatibility: garmin_bluetooth_compatibility) + peripheralManager = BLEPeripheralManagerZwift(disable_hr: disable_hr, garmin_bluetooth_compatibility: garmin_bluetooth_compatibility, tacx: tacx) } @objc public func updateHeartRate(HeartRate: UInt8) @@ -62,6 +62,7 @@ let TrainingStatusUuid = CBUUID(string: "0x2AD3"); class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { private var garmin_bluetooth_compatibility: Bool = false + private var tacx: Bool = false private var disable_hr: Bool = false private var peripheralManager: CBPeripheralManager! @@ -109,9 +110,10 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { private var notificationTimer: Timer! = nil //var delegate: BLEPeripheralManagerDelegate? - init(disable_hr: Bool, garmin_bluetooth_compatibility: Bool) { + init(disable_hr: Bool, garmin_bluetooth_compatibility: Bool, tacx: Bool) { super.init() self.disable_hr = disable_hr + self.tacx = tacx self.garmin_bluetooth_compatibility = garmin_bluetooth_compatibility peripheralManager = CBPeripheralManager(delegate: self, queue: nil) @@ -269,6 +271,10 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { let advertisementData = [CBAdvertisementDataLocalNameKey: "QZ", CBAdvertisementDataServiceUUIDsKey: [PowerServiceUUID]] as [String : Any] peripheralManager.startAdvertising(advertisementData) + } else if(tacx) { + let advertisementData = [CBAdvertisementDataLocalNameKey: "Tacx Neo 17867", + CBAdvertisementDataServiceUUIDsKey: [PowerServiceUUID, CSCServiceUUID]] as [String : Any] + peripheralManager.startAdvertising(advertisementData) } else if(disable_hr) { // useful in order to hide HR from Garmin devices let advertisementData = [CBAdvertisementDataLocalNameKey: "QZ", diff --git a/src/virtualdevices/virtualbike.cpp b/src/virtualdevices/virtualbike.cpp index f3fa5c936..cf72b1746 100644 --- a/src/virtualdevices/virtualbike.cpp +++ b/src/virtualdevices/virtualbike.cpp @@ -58,12 +58,12 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear #ifndef IO_UNDER_QT bool ios_peloton_workaround = settings.value(QZSettings::ios_peloton_workaround, QZSettings::default_ios_peloton_workaround).toBool(); - if ((ios_peloton_workaround && !cadence && !echelon && !ifit && !heart_only && !virtual_device_tacx) || garmin_bluetooth_compatibility) { + if ((ios_peloton_workaround && !cadence && !echelon && !ifit && !heart_only && !virtual_device_tacx) || garmin_bluetooth_compatibility || virtual_device_tacx) { qDebug() << "ios_zwift_workaround activated!"; h = new lockscreen(); h->virtualbike_zwift_ios( - settings.value(QZSettings::bike_heartrate_service, QZSettings::default_bike_heartrate_service).toBool(), garmin_bluetooth_compatibility); + settings.value(QZSettings::bike_heartrate_service, QZSettings::default_bike_heartrate_service).toBool(), garmin_bluetooth_compatibility, virtual_device_tacx); } else #endif From 0d247b732b9999ac5e4734752711c4de526fe9d8 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Mon, 24 Jun 2024 15:14:09 +0200 Subject: [PATCH 06/13] trying to add the service data for FTMS --- src/android/src/BleAdvertiser.java | 24 ++++++++++++++++++++++++ src/virtualdevices/virtualbike.cpp | 11 +++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/android/src/BleAdvertiser.java b/src/android/src/BleAdvertiser.java index 34a4a84ed..82698d325 100644 --- a/src/android/src/BleAdvertiser.java +++ b/src/android/src/BleAdvertiser.java @@ -39,6 +39,7 @@ public class BleAdvertiser { private static final UUID SERVICE_UUID = UUID.fromString("00001826-0000-1000-8000-00805f9b34fb"); private static final byte[] SERVICE_DATA_ROWER = {0x01, 0x10, 0x00}; private static final byte[] SERVICE_DATA_TREADMILL = {0x01, 0x01, 0x00}; + private static final byte[] SERVICE_DATA_BIKE = {0x01, 0x20, 0x00}; public static void startAdvertisingRower(Context context) { BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); @@ -86,6 +87,29 @@ public static void startAdvertisingTreadmill(Context context) { } } + public static void startAdvertisingBike(Context context) { + BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); + if (bluetoothManager != null) { + android.bluetooth.le.BluetoothLeAdvertiser advertiser = bluetoothManager.getAdapter().getBluetoothLeAdvertiser(); + + AdvertiseSettings settings = new AdvertiseSettings.Builder() + .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) + .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) + .setConnectable(true) + .build(); + + AdvertiseData advertiseData = new AdvertiseData.Builder() + .setIncludeDeviceName(true) + .addServiceUuid(new ParcelUuid(SERVICE_UUID)) + .addServiceData(new ParcelUuid(SERVICE_UUID), SERVICE_DATA_BIKE) + .build(); + + if (advertiser != null) { + advertiser.startAdvertising(settings, advertiseData, advertiseCallback); + } + } + } + private static AdvertiseCallback advertiseCallback = new AdvertiseCallback() { @Override public void onStartSuccess(AdvertiseSettings settingsInEffect) { diff --git a/src/virtualdevices/virtualbike.cpp b/src/virtualdevices/virtualbike.cpp index cf72b1746..db495f75f 100644 --- a/src/virtualdevices/virtualbike.cpp +++ b/src/virtualdevices/virtualbike.cpp @@ -446,7 +446,12 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear pars.setInterval(100, 100); } +#ifdef Q_OS_ANDROID + QAndroidJniObject::callStaticMethod("org/cagnulen/qdomyoszwift/BleAdvertiser", "startAdvertisingBike", + "(Landroid/content/Context;)V", QtAndroid::androidContext().object()); +#else leController->startAdvertising(pars, advertisingData, advertisingData); +#endif //! [Start Advertising] } @@ -996,9 +1001,15 @@ void virtualbike::reconnect() { serviceHR = leController->addService(serviceDataHR); #endif +#ifdef Q_OS_ANDROID + QAndroidJniObject::callStaticMethod("org/cagnulen/qdomyoszwift/BleAdvertiser", "startAdvertisingBike", + "(Landroid/content/Context;)V", QtAndroid::androidContext().object()); +#else QLowEnergyAdvertisingParameters pars; pars.setInterval(100, 100); leController->startAdvertising(pars, advertisingData, advertisingData); +#endif + } void virtualbike::bikeProvider() { From 3e0eeb39597e63f929e39953110fa51e7ff19000 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Mon, 24 Jun 2024 15:34:56 +0200 Subject: [PATCH 07/13] Update virtualbike.cpp --- src/virtualdevices/virtualbike.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/virtualdevices/virtualbike.cpp b/src/virtualdevices/virtualbike.cpp index db495f75f..f955a4db8 100644 --- a/src/virtualdevices/virtualbike.cpp +++ b/src/virtualdevices/virtualbike.cpp @@ -7,6 +7,12 @@ #include #include +#ifdef Q_OS_ANDROID +#include "androidactivityresultreceiver.h" +#include "keepawakehelper.h" +#include +#endif + using namespace std::chrono_literals; virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHeartService, uint8_t bikeResistanceOffset, From 5acebbdc8d8dd718e38a495b4a5735804ba82fb7 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Tue, 25 Jun 2024 10:19:28 +0200 Subject: [PATCH 08/13] Update BleAdvertiser.java --- src/android/src/BleAdvertiser.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/android/src/BleAdvertiser.java b/src/android/src/BleAdvertiser.java index 82698d325..803cf23b6 100644 --- a/src/android/src/BleAdvertiser.java +++ b/src/android/src/BleAdvertiser.java @@ -101,6 +101,9 @@ public static void startAdvertisingBike(Context context) { AdvertiseData advertiseData = new AdvertiseData.Builder() .setIncludeDeviceName(true) .addServiceUuid(new ParcelUuid(SERVICE_UUID)) + .addServiceUuid(new ParcelUuid(UUID.fromString("00001818-0000-1000-8000-00805F9B34FB"))) // UUID 16 bit + .addServiceUuid(new ParcelUuid(UUID.fromString("00001816-0000-1000-8000-00805F9B34FB"))) // UUID 16 bit + .addServiceUuid(new ParcelUuid(UUID.fromString("6e40fec1-b5a3-f393-e0a9-e50e24dcca9e"))) // UUID 128 bit .addServiceData(new ParcelUuid(SERVICE_UUID), SERVICE_DATA_BIKE) .build(); From 9c510c9910ab348920b04c1fa73eff540524b1b3 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Tue, 25 Jun 2024 11:13:08 +0200 Subject: [PATCH 09/13] Update qzsettings.cpp --- src/qzsettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qzsettings.cpp b/src/qzsettings.cpp index f7e0008ea..fc3e5db8c 100644 --- a/src/qzsettings.cpp +++ b/src/qzsettings.cpp @@ -743,7 +743,7 @@ const QString QZSettings::proform_bike_325_csx = QStringLiteral("proform_bike_32 const QString QZSettings::strava_upload_mode = QStringLiteral("strava_upload_mode"); const QString QZSettings::default_strava_upload_mode = QStringLiteral("Always"); -const uint32_t allSettingsCount = 625; +const uint32_t allSettingsCount = 626; QVariant allSettings[allSettingsCount][2] = { {QZSettings::cryptoKeySettingsProfiles, QZSettings::default_cryptoKeySettingsProfiles}, From d2975953dc32c894a255366feaafff1c2cf400b4 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Tue, 25 Jun 2024 11:58:13 +0200 Subject: [PATCH 10/13] it can't broadcast otherwise --- src/android/src/BleAdvertiser.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/android/src/BleAdvertiser.java b/src/android/src/BleAdvertiser.java index 803cf23b6..82698d325 100644 --- a/src/android/src/BleAdvertiser.java +++ b/src/android/src/BleAdvertiser.java @@ -101,9 +101,6 @@ public static void startAdvertisingBike(Context context) { AdvertiseData advertiseData = new AdvertiseData.Builder() .setIncludeDeviceName(true) .addServiceUuid(new ParcelUuid(SERVICE_UUID)) - .addServiceUuid(new ParcelUuid(UUID.fromString("00001818-0000-1000-8000-00805F9B34FB"))) // UUID 16 bit - .addServiceUuid(new ParcelUuid(UUID.fromString("00001816-0000-1000-8000-00805F9B34FB"))) // UUID 16 bit - .addServiceUuid(new ParcelUuid(UUID.fromString("6e40fec1-b5a3-f393-e0a9-e50e24dcca9e"))) // UUID 128 bit .addServiceData(new ParcelUuid(SERVICE_UUID), SERVICE_DATA_BIKE) .build(); From 037f7405bbc11b1822737ef4f957eb42f918fe83 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Thu, 14 Nov 2024 11:16:49 +0100 Subject: [PATCH 11/13] Update virtualbike.cpp --- src/virtualdevices/virtualbike.cpp | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/virtualdevices/virtualbike.cpp b/src/virtualdevices/virtualbike.cpp index 0bbc42153..8d930d0b9 100644 --- a/src/virtualdevices/virtualbike.cpp +++ b/src/virtualdevices/virtualbike.cpp @@ -134,6 +134,43 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear advertisingData.setServices(services); //! [Advertising Data] + if(virtual_device_tacx) { + // Add Device Information Service + QLowEnergyCharacteristicData manufacturerNameChar; + manufacturerNameChar.setUuid(QBluetoothUuid::CharacteristicType::ManufacturerNameString); + manufacturerNameChar.setProperties(QLowEnergyCharacteristic::Read); + manufacturerNameChar.setValue(QByteArray("Tacx")); + + QLowEnergyCharacteristicData modelNumberChar; + modelNumberChar.setUuid(QBluetoothUuid::CharacteristicType::ModelNumberString); + modelNumberChar.setProperties(QLowEnergyCharacteristic::Read); + modelNumberChar.setValue(QByteArray("Neo")); + + QLowEnergyCharacteristicData serialNumberChar; + serialNumberChar.setUuid(QBluetoothUuid::CharacteristicType::SerialNumberString); + serialNumberChar.setProperties(QLowEnergyCharacteristic::Read); + serialNumberChar.setValue(QByteArray("17867")); + + QLowEnergyCharacteristicData hardwareRevChar; + hardwareRevChar.setUuid(QBluetoothUuid::CharacteristicType::HardwareRevisionString); + hardwareRevChar.setProperties(QLowEnergyCharacteristic::Read); + hardwareRevChar.setValue(QByteArray("0")); + + QLowEnergyCharacteristicData firmwareRevChar; + firmwareRevChar.setUuid(QBluetoothUuid::CharacteristicType::FirmwareRevisionString); + firmwareRevChar.setProperties(QLowEnergyCharacteristic::Read); + firmwareRevChar.setValue(QByteArray("0.7.4")); + + // Create Device Information Service + serviceDataDIS.setType(QLowEnergyServiceData::ServiceTypePrimary); + serviceDataDIS.setUuid(QBluetoothUuid::DeviceInformation); + serviceDataDIS.addCharacteristic(manufacturerNameChar); + serviceDataDIS.addCharacteristic(modelNumberChar); + serviceDataDIS.addCharacteristic(serialNumberChar); + serviceDataDIS.addCharacteristic(hardwareRevChar); + serviceDataDIS.addCharacteristic(firmwareRevChar); + } + if (!echelon && !ifit) { if (!heart_only) { if (!cadence && !power) { @@ -483,6 +520,11 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear } QThread::msleep(100); // give time to Android to add the service async.ly + if(virtual_device_tacx) { + serviceDIS = leController->addService(serviceDataDIS); + QThread::msleep(100); // give time to Android to add the service async.ly + } + if (battery) { serviceBattery = leController->addService(serviceDataBattery); } @@ -1363,6 +1405,11 @@ void virtualbike::reconnect() { } QThread::msleep(100); // give time to Android to add the service async.ly + if(virtual_device_tacx) { + serviceDIS = leController->addService(serviceDataDIS); + QThread::msleep(100); // give time to Android to add the service async.ly + } + if (battery) serviceBattery = leController->addService(serviceDataBattery); From cedc64f6647d02356297254a907ab3ed9553739f Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Thu, 14 Nov 2024 11:17:22 +0100 Subject: [PATCH 12/13] Update virtualbike.h --- src/virtualdevices/virtualbike.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/virtualdevices/virtualbike.h b/src/virtualdevices/virtualbike.h index ab93d9e92..eb1111ae5 100644 --- a/src/virtualdevices/virtualbike.h +++ b/src/virtualdevices/virtualbike.h @@ -61,6 +61,8 @@ class virtualbike : public virtualdevice { QLowEnergyServiceData serviceEchelon; QLowEnergyServiceData serviceDataWattAtomBike; QLowEnergyServiceData serviceDataZwiftPlayBike; + QLowEnergyService *serviceDIS = nullptr; + QLowEnergyServiceData serviceDataDIS; QTimer bikeTimer; bluetoothdevice *Bike; CharacteristicWriteProcessor2AD9 *writeP2AD9 = 0; From 635e8bd76064f5440fa6ecc493bedc445c6d59a6 Mon Sep 17 00:00:00 2001 From: Roberto Viola Date: Thu, 14 Nov 2024 11:52:36 +0100 Subject: [PATCH 13/13] Update virtualbike.cpp --- src/virtualdevices/virtualbike.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/virtualdevices/virtualbike.cpp b/src/virtualdevices/virtualbike.cpp index 8d930d0b9..2e79e1d53 100644 --- a/src/virtualdevices/virtualbike.cpp +++ b/src/virtualdevices/virtualbike.cpp @@ -1369,6 +1369,7 @@ void virtualbike::reconnect() { bool echelon = settings.value(QZSettings::virtual_device_echelon, QZSettings::default_virtual_device_echelon).toBool(); bool ifit = settings.value(QZSettings::virtual_device_ifit, QZSettings::default_virtual_device_ifit).toBool(); + bool virtual_device_tacx = settings.value(QZSettings::virtual_device_tacx, QZSettings::default_virtual_device_tacx).toBool(); qDebug() << QStringLiteral("virtualbike::reconnect"); leController->disconnectFromDevice();