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

let's see if the tacx app gets QZ #2336

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/android/src/BleAdvertiser.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions src/ios/BLEPeripheralManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
3 changes: 2 additions & 1 deletion src/ios/lockscreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ 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, bool zwift_play_emulator, bool watt_bike_emulator);
void virtualbike_zwift_ios(bool disable_hr, bool garmin_bluetooth_compatibility, bool zwift_play_emulator, bool watt_bike_emulator, bool tacx);

double virtualbike_getCurrentSlope();
double virtualbike_getCurrentCRR();
double virtualbike_getCurrentCW();
Expand Down
4 changes: 2 additions & 2 deletions src/ios/lockscreen.mm
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@
[_virtualbike updateCadenceWithCrankRevolutions:crankRevolutions LastCrankEventTime:lastCrankEventTime];
}

void lockscreen::virtualbike_zwift_ios(bool disable_hr, bool garmin_bluetooth_compatibility, bool zwift_play_emulator, bool watt_bike_emulator)
void lockscreen::virtualbike_zwift_ios(bool disable_hr, bool garmin_bluetooth_compatibility, bool zwift_play_emulator, bool watt_bike_emulator, bool tacx)
{
_virtualbike_zwift = [[virtualbike_zwift alloc] initWithDisable_hr:disable_hr garmin_bluetooth_compatibility:garmin_bluetooth_compatibility zwift_play_emulator:zwift_play_emulator watt_bike_emulator:watt_bike_emulator];
_virtualbike_zwift = [[virtualbike_zwift alloc] initWithDisable_hr:disable_hr garmin_bluetooth_compatibility:garmin_bluetooth_compatibility zwift_play_emulator:zwift_play_emulator watt_bike_emulator:watt_bike_emulator tacx:tacx];
}

void lockscreen::virtualrower_ios()
Expand Down
13 changes: 10 additions & 3 deletions src/ios/virtualbike_zwift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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, zwift_play_emulator: Bool, watt_bike_emulator: Bool) {
@objc public init(disable_hr: Bool, garmin_bluetooth_compatibility: Bool, zwift_play_emulator: Bool, watt_bike_emulator: Bool, tacx: Bool) {
super.init()
peripheralManager = BLEPeripheralManagerZwift(disable_hr: disable_hr, garmin_bluetooth_compatibility: garmin_bluetooth_compatibility, zwift_play_emulator: zwift_play_emulator, watt_bike_emulator: watt_bike_emulator)
peripheralManager = BLEPeripheralManagerZwift(disable_hr: disable_hr, garmin_bluetooth_compatibility: garmin_bluetooth_compatibility, zwift_play_emulator: zwift_play_emulator, watt_bike_emulator: watt_bike_emulator, tacx: tacx)
}

@objc public func updateHeartRate(HeartRate: UInt8)
Expand Down Expand Up @@ -63,6 +63,7 @@ let TrainingStatusUuid = CBUUID(string: "0x2AD3");

class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate {
private var garmin_bluetooth_compatibility: Bool = false
private var tacx: Bool = false
private var zwift_play_emulator: Bool = false
private var watt_bike_emulator: Bool = false
private var disable_hr: Bool = false
Expand Down Expand Up @@ -128,9 +129,11 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate {
let SwiftDebug = swiftDebug()
//var delegate: BLEPeripheralManagerDelegate?

init(disable_hr: Bool, garmin_bluetooth_compatibility: Bool, zwift_play_emulator: Bool, watt_bike_emulator: Bool) {

init(disable_hr: Bool, garmin_bluetooth_compatibility: Bool, zwift_play_emulator: Bool, watt_bike_emulator: Bool, tacx: Bool) {
super.init()
self.disable_hr = disable_hr
self.tacx = tacx
self.garmin_bluetooth_compatibility = garmin_bluetooth_compatibility
self.zwift_play_emulator = zwift_play_emulator
self.watt_bike_emulator = watt_bike_emulator
Expand Down Expand Up @@ -354,6 +357,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",
Expand Down
4 changes: 3 additions & 1 deletion src/qzsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ 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 QString QZSettings::proform_bike_325_csx = QStringLiteral("proform_bike_325_csx");
const QString QZSettings::strava_upload_mode = QStringLiteral("strava_upload_mode");
const QString QZSettings::default_strava_upload_mode = QStringLiteral("Always");
Expand Down Expand Up @@ -786,7 +787,7 @@ const QString QZSettings::proform_treadmill_c700 = QStringLiteral("proform_tread
const QString QZSettings::sram_axs_controller = QStringLiteral("sram_axs_controller");
const QString QZSettings::proform_treadmill_c960i = QStringLiteral("proform_treadmill_c960i");

const uint32_t allSettingsCount = 665;
const uint32_t allSettingsCount = 666;

QVariant allSettings[allSettingsCount][2] = {
{QZSettings::cryptoKeySettingsProfiles, QZSettings::default_cryptoKeySettingsProfiles},
Expand Down Expand Up @@ -1416,6 +1417,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},
{QZSettings::proform_bike_325_csx, QZSettings::default_proform_bike_325_csx},
{QZSettings::strava_upload_mode, QZSettings::default_strava_upload_mode},
{QZSettings::proform_treadmill_705_cst_V78_239, QZSettings::default_proform_treadmill_705_cst_V78_239},
Expand Down
3 changes: 3 additions & 0 deletions src/qzsettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

static const QString proform_bike_325_csx;
static constexpr bool default_proform_bike_325_csx = false;

Expand Down
32 changes: 30 additions & 2 deletions src/settings.qml
Original file line number Diff line number Diff line change
Expand Up @@ -938,10 +938,10 @@ import QtQuick.Dialogs 1.0
property bool proform_595i_proshox2: false

// from version 2.16.55
property bool proform_treadmill_8_7: false
property bool proform_treadmill_8_7: false

// from version 2.16.56
property bool proform_bike_325_csx: false
property bool proform_bike_325_csx: false

// from version 2.16.58
property string strava_upload_mode: "Always"
Expand Down Expand Up @@ -1009,6 +1009,7 @@ import QtQuick.Dialogs 1.0
property bool proform_treadmill_c700: false
property bool sram_axs_controller: false
property bool proform_treadmill_c960i: false
property bool virtual_device_tacx: false
}

function paddingZeros(text, limit) {
Expand Down Expand Up @@ -10433,6 +10434,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 {
Expand Down
Loading
Loading