mirror of
https://github.com/cagnulein/qdomyos-zwift.git
synced 2026-02-18 00:17:41 +01:00
Compare commits
9 Commits
ant-remote
...
Click-and-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12920d10a8 | ||
|
|
dd2bfc4e1b | ||
|
|
06fd78378e | ||
|
|
f28574245c | ||
|
|
b964c523dd | ||
|
|
0721bc3ec5 | ||
|
|
3f783305b2 | ||
|
|
be29180e48 | ||
|
|
19c65d7d90 |
@@ -4455,7 +4455,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1161;
|
||||
CURRENT_PROJECT_VERSION = 1164;
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -4655,7 +4655,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1161;
|
||||
CURRENT_PROJECT_VERSION = 1164;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
@@ -4891,7 +4891,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1161;
|
||||
CURRENT_PROJECT_VERSION = 1164;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -4987,7 +4987,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1161;
|
||||
CURRENT_PROJECT_VERSION = 1164;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = YES;
|
||||
@@ -5079,7 +5079,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1161;
|
||||
CURRENT_PROJECT_VERSION = 1164;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -5195,7 +5195,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1161;
|
||||
CURRENT_PROJECT_VERSION = 1164;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
|
||||
ENABLE_BITCODE = YES;
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.widget.Toast;
|
||||
import org.cagnulen.qdomyoszwift.QLog;
|
||||
import android.content.Intent;
|
||||
|
||||
|
||||
public class Ant {
|
||||
private ChannelService.ChannelServiceComm mChannelService = null;
|
||||
private boolean mChannelServiceBound = false;
|
||||
@@ -34,27 +33,23 @@ public class Ant {
|
||||
static boolean speedRequest = false;
|
||||
static boolean heartRequest = false;
|
||||
static boolean bikeRequest = false; // Added bike request flag
|
||||
static boolean remoteControlRequest = false; // Added remote control request flag
|
||||
static boolean garminKey = false;
|
||||
static boolean treadmill = false;
|
||||
static boolean technoGymGroupCycle = false;
|
||||
static int antBikeDeviceNumber = 0;
|
||||
static int antHeartDeviceNumber = 0;
|
||||
static int antRemoteControlDeviceNumber = 0; // Added remote control device number
|
||||
|
||||
// Updated antStart method with RemoteControlRequest parameter at the end
|
||||
public void antStart(Activity a, boolean SpeedRequest, boolean HeartRequest, boolean GarminKey, boolean Treadmill, boolean BikeRequest, boolean TechnoGymGroupCycle, int AntBikeDeviceNumber, int AntHeartDeviceNumber, boolean RemoteControlRequest, int AntRemoteControlDeviceNumber) {
|
||||
// Updated antStart method with BikeRequest parameter at the end
|
||||
public void antStart(Activity a, boolean SpeedRequest, boolean HeartRequest, boolean GarminKey, boolean Treadmill, boolean BikeRequest, boolean TechnoGymGroupCycle, int AntBikeDeviceNumber, int AntHeartDeviceNumber) {
|
||||
QLog.v(TAG, "antStart");
|
||||
speedRequest = SpeedRequest;
|
||||
heartRequest = HeartRequest;
|
||||
treadmill = Treadmill;
|
||||
garminKey = GarminKey;
|
||||
bikeRequest = BikeRequest; // Set bike request flag
|
||||
remoteControlRequest = RemoteControlRequest; // Set remote control request flag
|
||||
technoGymGroupCycle = TechnoGymGroupCycle;
|
||||
antBikeDeviceNumber = AntBikeDeviceNumber;
|
||||
antHeartDeviceNumber = AntHeartDeviceNumber;
|
||||
antRemoteControlDeviceNumber = AntRemoteControlDeviceNumber;
|
||||
activity = a;
|
||||
if(a != null)
|
||||
QLog.v(TAG, "antStart activity is valid");
|
||||
@@ -164,29 +159,14 @@ public class Ant {
|
||||
return mChannelService.isBikeConnected();
|
||||
}
|
||||
|
||||
public void updateBikeTransmitterExtendedMetrics(long distanceMeters, int heartRate,
|
||||
double elapsedTimeSeconds, int resistance,
|
||||
public void updateBikeTransmitterExtendedMetrics(long distanceMeters, int heartRate,
|
||||
double elapsedTimeSeconds, int resistance,
|
||||
double inclination) {
|
||||
if(mChannelService == null)
|
||||
return;
|
||||
QLog.v(TAG, "updateBikeTransmitterExtendedMetrics");
|
||||
mChannelService.updateBikeTransmitterExtendedMetrics(distanceMeters, heartRate,
|
||||
elapsedTimeSeconds, resistance,
|
||||
mChannelService.updateBikeTransmitterExtendedMetrics(distanceMeters, heartRate,
|
||||
elapsedTimeSeconds, resistance,
|
||||
inclination);
|
||||
}
|
||||
|
||||
// Remote Control methods
|
||||
public boolean isRemoteControlConnected() {
|
||||
if(mChannelService == null)
|
||||
return false;
|
||||
QLog.v(TAG, "isRemoteControlConnected");
|
||||
return mChannelService.isRemoteControlConnected();
|
||||
}
|
||||
|
||||
public void setRemoteControlDeviceNumber(int deviceNumber) {
|
||||
if(mChannelService == null)
|
||||
return;
|
||||
QLog.v(TAG, "setRemoteControlDeviceNumber: " + deviceNumber);
|
||||
mChannelService.setRemoteControlDeviceNumber(deviceNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,438 +0,0 @@
|
||||
/*
|
||||
* ANT+ Remote Control implementation for QDomyos-Zwift
|
||||
* Based on Golden Cheetah RemoteControl implementation
|
||||
* Maps ANT+ remote control commands to workout controls
|
||||
*/
|
||||
package org.cagnulen.qdomyoszwift;
|
||||
|
||||
import com.dsi.ant.channel.AntChannel;
|
||||
import com.dsi.ant.channel.AntCommandFailedException;
|
||||
import com.dsi.ant.channel.IAntChannelEventHandler;
|
||||
import com.dsi.ant.message.ChannelId;
|
||||
import com.dsi.ant.message.ChannelType;
|
||||
import com.dsi.ant.message.EventCode;
|
||||
import com.dsi.ant.message.fromant.AcknowledgedDataMessage;
|
||||
import com.dsi.ant.message.fromant.BroadcastDataMessage;
|
||||
import com.dsi.ant.message.fromant.ChannelEventMessage;
|
||||
import com.dsi.ant.message.fromant.MessageFromAntType;
|
||||
import com.dsi.ant.message.ipc.AntMessageParcel;
|
||||
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import org.cagnulen.qdomyoszwift.QLog;
|
||||
|
||||
/**
|
||||
* ANT+ Remote Control Channel Controller
|
||||
* Handles ANT+ Control Device Profile (Device Type 0x10)
|
||||
*/
|
||||
public class AntRemoteControl {
|
||||
private static final String TAG = "AntRemoteControl";
|
||||
|
||||
// ANT+ Control Device Profile constants
|
||||
private static final int CONTROL_DEVICE_TYPE = 0x10;
|
||||
private static final int CONTROL_TRANSMISSION_TYPE = 0x05;
|
||||
private static final short CONTROL_PERIOD = 8192; // 4 Hz
|
||||
private static final int CONTROL_FREQUENCY = 57; // 2457 MHz
|
||||
|
||||
// ANT+ Control Generic Command Page
|
||||
private static final byte ANT_CONTROL_GENERIC_CMD_PAGE = 0x49;
|
||||
|
||||
// ANT+ Generic Commands (from Golden Cheetah)
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_MENU_UP = 0x00;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_MENU_DOWN = 0x01;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_MENU_SELECT = 0x02;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_MENU_BACK = 0x03;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_HOME = 0x04;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_START = 0x20;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_STOP = 0x21;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_RESET = 0x22;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_LENGTH = 0x23;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_LAP = 0x24;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_USER_1 = 0x8000;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_USER_2 = 0x8001;
|
||||
private static final int ANT_CONTROL_GENERIC_CMD_USER_3 = 0x8002;
|
||||
|
||||
private AntChannel mAntChannel;
|
||||
private ChannelController mChannelController;
|
||||
private boolean isChannelOpen = false;
|
||||
private int deviceNumber = 0; // 0 means wildcard - accept any remote
|
||||
|
||||
// Native methods for communicating with Qt layer
|
||||
public static native void nativeOnRemoteCommand(int command);
|
||||
public static native void nativeGearUp();
|
||||
public static native void nativeGearDown();
|
||||
|
||||
/**
|
||||
* Channel Controller for handling ANT+ events
|
||||
*/
|
||||
private class ChannelController implements IAntChannelEventHandler {
|
||||
|
||||
@Override
|
||||
public void onChannelDeath() {
|
||||
QLog.w(TAG, "onChannelDeath: Remote Control Channel Death - cleaning up");
|
||||
isChannelOpen = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveMessage(MessageFromAntType messageType, AntMessageParcel antParcel) {
|
||||
QLog.v(TAG, "onReceiveMessage: messageType=" + messageType + ", parcel=" + antParcel);
|
||||
|
||||
switch(messageType) {
|
||||
case ACKNOWLEDGED_DATA:
|
||||
QLog.d(TAG, "onReceiveMessage: Received ACKNOWLEDGED_DATA");
|
||||
AcknowledgedDataMessage ackMsg = new AcknowledgedDataMessage(antParcel);
|
||||
byte[] ackPayload = ackMsg.getPayload();
|
||||
QLog.v(TAG, "onReceiveMessage: ACKNOWLEDGED_DATA payload length=" + (ackPayload != null ? ackPayload.length : 0));
|
||||
handleDataMessage(ackPayload);
|
||||
break;
|
||||
case BROADCAST_DATA:
|
||||
QLog.d(TAG, "onReceiveMessage: Received BROADCAST_DATA");
|
||||
BroadcastDataMessage broadcastMsg = new BroadcastDataMessage(antParcel);
|
||||
byte[] broadcastPayload = broadcastMsg.getPayload();
|
||||
QLog.v(TAG, "onReceiveMessage: BROADCAST_DATA payload length=" + (broadcastPayload != null ? broadcastPayload.length : 0));
|
||||
handleDataMessage(broadcastPayload);
|
||||
break;
|
||||
case CHANNEL_EVENT:
|
||||
ChannelEventMessage eventMessage = new ChannelEventMessage(antParcel);
|
||||
EventCode code = eventMessage.getEventCode();
|
||||
QLog.d(TAG, "onReceiveMessage: CHANNEL_EVENT - eventCode=" + code);
|
||||
|
||||
switch(code) {
|
||||
/* case CHANNEL_IN_WRONG_STATE:
|
||||
QLog.w(TAG, "onReceiveMessage: CHANNEL_IN_WRONG_STATE error");
|
||||
break;*/
|
||||
case CHANNEL_COLLISION:
|
||||
QLog.w(TAG, "onReceiveMessage: CHANNEL_COLLISION error");
|
||||
break;
|
||||
case TRANSFER_TX_FAILED:
|
||||
QLog.w(TAG, "onReceiveMessage: TRANSFER_TX_FAILED error");
|
||||
break;
|
||||
case RX_SEARCH_TIMEOUT:
|
||||
QLog.i(TAG, "onReceiveMessage: RX_SEARCH_TIMEOUT - no remote control found");
|
||||
break;
|
||||
case CHANNEL_CLOSED:
|
||||
QLog.i(TAG, "onReceiveMessage: CHANNEL_CLOSED");
|
||||
isChannelOpen = false;
|
||||
break;
|
||||
default:
|
||||
QLog.v(TAG, "onReceiveMessage: Other channel event=" + code);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
QLog.d(TAG, "onReceiveMessage: Unhandled messageType=" + messageType + ", parcel=" + antParcel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incoming data messages from ANT+ remote control
|
||||
*/
|
||||
private void handleDataMessage(byte[] payload) {
|
||||
QLog.v(TAG, "handleDataMessage: called with payload=" + (payload != null ? "length=" + payload.length : "null"));
|
||||
|
||||
if (payload == null) {
|
||||
QLog.w(TAG, "handleDataMessage: payload is null, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload.length < 8) {
|
||||
QLog.w(TAG, "handleDataMessage: payload too short (length=" + payload.length + "), expected 8 bytes");
|
||||
return;
|
||||
}
|
||||
|
||||
// Log raw payload for debugging
|
||||
StringBuilder payloadHex = new StringBuilder();
|
||||
for (int i = 0; i < payload.length; i++) {
|
||||
payloadHex.append(String.format("%02X ", payload[i]));
|
||||
}
|
||||
QLog.v(TAG, "handleDataMessage: raw payload: " + payloadHex.toString());
|
||||
|
||||
// Check if this is a Generic Command Page
|
||||
byte pageNumber = payload[0];
|
||||
QLog.d(TAG, "handleDataMessage: pageNumber=0x" + Integer.toHexString(pageNumber & 0xFF) +
|
||||
" (expected=0x" + Integer.toHexString(ANT_CONTROL_GENERIC_CMD_PAGE & 0xFF) + ")");
|
||||
|
||||
if (pageNumber != ANT_CONTROL_GENERIC_CMD_PAGE) {
|
||||
QLog.w(TAG, "handleDataMessage: not a Generic Command Page, ignoring (pageNumber=0x" +
|
||||
Integer.toHexString(pageNumber & 0xFF) + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract command from payload
|
||||
// Command is in bytes 1-2 (little endian)
|
||||
int command = ((payload[2] & 0xFF) << 8) | (payload[1] & 0xFF);
|
||||
|
||||
QLog.i(TAG, "handleDataMessage: extracted ANT+ Remote Command=0x" + Integer.toHexString(command) +
|
||||
" from bytes[1]=0x" + Integer.toHexString(payload[1] & 0xFF) +
|
||||
", bytes[2]=0x" + Integer.toHexString(payload[2] & 0xFF));
|
||||
|
||||
// Map commands to actions
|
||||
handleRemoteCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle remote control commands and map them to QDomyos-Zwift actions
|
||||
*/
|
||||
private void handleRemoteCommand(int command) {
|
||||
QLog.d(TAG, "handleRemoteCommand: processing command=0x" + Integer.toHexString(command));
|
||||
|
||||
switch(command) {
|
||||
case ANT_CONTROL_GENERIC_CMD_MENU_UP:
|
||||
QLog.i(TAG, "handleRemoteCommand: MENU_UP -> Gear Up (like Zwift Click)");
|
||||
try {
|
||||
nativeGearUp();
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeGearUp() called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeGearUp()", e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_CONTROL_GENERIC_CMD_MENU_DOWN:
|
||||
QLog.i(TAG, "handleRemoteCommand: MENU_DOWN -> Gear Down (like Zwift Click)");
|
||||
try {
|
||||
nativeGearDown();
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeGearDown() called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeGearDown()", e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_CONTROL_GENERIC_CMD_MENU_SELECT:
|
||||
QLog.i(TAG, "handleRemoteCommand: MENU_SELECT -> Select action");
|
||||
try {
|
||||
nativeOnRemoteCommand(command);
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeOnRemoteCommand(SELECT) called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeOnRemoteCommand(SELECT)", e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_CONTROL_GENERIC_CMD_MENU_BACK:
|
||||
QLog.i(TAG, "handleRemoteCommand: MENU_BACK -> Back action");
|
||||
try {
|
||||
nativeOnRemoteCommand(command);
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeOnRemoteCommand(BACK) called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeOnRemoteCommand(BACK)", e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_CONTROL_GENERIC_CMD_HOME:
|
||||
QLog.i(TAG, "handleRemoteCommand: HOME -> Home action");
|
||||
try {
|
||||
nativeOnRemoteCommand(command);
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeOnRemoteCommand(HOME) called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeOnRemoteCommand(HOME)", e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_CONTROL_GENERIC_CMD_START:
|
||||
QLog.i(TAG, "handleRemoteCommand: START -> Start workout");
|
||||
try {
|
||||
nativeOnRemoteCommand(command);
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeOnRemoteCommand(START) called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeOnRemoteCommand(START)", e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_CONTROL_GENERIC_CMD_STOP:
|
||||
QLog.i(TAG, "handleRemoteCommand: STOP -> Stop workout");
|
||||
try {
|
||||
nativeOnRemoteCommand(command);
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeOnRemoteCommand(STOP) called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeOnRemoteCommand(STOP)", e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_CONTROL_GENERIC_CMD_LAP:
|
||||
QLog.i(TAG, "handleRemoteCommand: LAP -> Lap marker");
|
||||
try {
|
||||
nativeOnRemoteCommand(command);
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeOnRemoteCommand(LAP) called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeOnRemoteCommand(LAP)", e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_CONTROL_GENERIC_CMD_RESET:
|
||||
QLog.i(TAG, "handleRemoteCommand: RESET -> Reset action");
|
||||
try {
|
||||
nativeOnRemoteCommand(command);
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeOnRemoteCommand(RESET) called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeOnRemoteCommand(RESET)", e);
|
||||
}
|
||||
break;
|
||||
|
||||
case ANT_CONTROL_GENERIC_CMD_USER_1:
|
||||
case ANT_CONTROL_GENERIC_CMD_USER_2:
|
||||
case ANT_CONTROL_GENERIC_CMD_USER_3:
|
||||
QLog.i(TAG, "handleRemoteCommand: USER_" + (command - ANT_CONTROL_GENERIC_CMD_USER_1 + 1) + " -> User action");
|
||||
try {
|
||||
nativeOnRemoteCommand(command);
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeOnRemoteCommand(USER) called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeOnRemoteCommand(USER)", e);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
QLog.w(TAG, "handleRemoteCommand: Unknown/unmapped command=0x" + Integer.toHexString(command));
|
||||
try {
|
||||
nativeOnRemoteCommand(command);
|
||||
QLog.d(TAG, "handleRemoteCommand: nativeOnRemoteCommand(UNKNOWN) called successfully");
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "handleRemoteCommand: Error calling nativeOnRemoteCommand(UNKNOWN)", e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public AntRemoteControl() {
|
||||
QLog.i(TAG, "AntRemoteControl: constructor - initializing ANT+ Remote Control");
|
||||
mChannelController = new ChannelController();
|
||||
QLog.d(TAG, "AntRemoteControl: constructor completed, channel controller created");
|
||||
}
|
||||
|
||||
/**
|
||||
* Open ANT+ remote control channel
|
||||
*/
|
||||
public boolean openChannel(AntChannel antChannel) {
|
||||
QLog.i(TAG, "openChannel: request to open ANT+ Remote Control channel");
|
||||
|
||||
if (isChannelOpen) {
|
||||
QLog.w(TAG, "openChannel: Remote control channel already open, ignoring request");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (antChannel == null) {
|
||||
QLog.e(TAG, "openChannel: antChannel is null, cannot proceed");
|
||||
return false;
|
||||
}
|
||||
|
||||
mAntChannel = antChannel;
|
||||
QLog.d(TAG, "openChannel: antChannel assigned");
|
||||
|
||||
try {
|
||||
// Configure the channel
|
||||
ChannelId channelId = new ChannelId(deviceNumber, CONTROL_DEVICE_TYPE, CONTROL_TRANSMISSION_TYPE);
|
||||
QLog.d(TAG, "openChannel: created ChannelId - deviceNumber=" + deviceNumber +
|
||||
", deviceType=0x" + Integer.toHexString(CONTROL_DEVICE_TYPE) +
|
||||
", transmissionType=0x" + Integer.toHexString(CONTROL_TRANSMISSION_TYPE));
|
||||
|
||||
QLog.i(TAG, "openChannel: configuring ANT+ Remote Control channel" +
|
||||
" (deviceNumber=" + deviceNumber + ", frequency=" + CONTROL_FREQUENCY +
|
||||
"MHz, period=" + CONTROL_PERIOD + ")");
|
||||
|
||||
// Assign the channel with slave configuration
|
||||
QLog.d(TAG, "openChannel: assigning channel as SLAVE_RECEIVE_ONLY");
|
||||
mAntChannel.assign(ChannelType.SLAVE_RECEIVE_ONLY);
|
||||
|
||||
// Set the channel ID
|
||||
QLog.d(TAG, "openChannel: setting channel ID");
|
||||
mAntChannel.setChannelId(channelId);
|
||||
|
||||
// Set the period
|
||||
QLog.d(TAG, "openChannel: setting period=" + CONTROL_PERIOD);
|
||||
mAntChannel.setPeriod(CONTROL_PERIOD);
|
||||
|
||||
// Set the RF frequency
|
||||
QLog.d(TAG, "openChannel: setting RF frequency=" + CONTROL_FREQUENCY);
|
||||
mAntChannel.setRfFrequency(CONTROL_FREQUENCY);
|
||||
|
||||
// Register event handler
|
||||
QLog.d(TAG, "openChannel: registering channel event handler");
|
||||
mAntChannel.setChannelEventHandler(mChannelController);
|
||||
|
||||
// Open the channel
|
||||
QLog.d(TAG, "openChannel: opening the channel");
|
||||
mAntChannel.open();
|
||||
|
||||
isChannelOpen = true;
|
||||
QLog.i(TAG, "openChannel: ANT+ Remote Control channel opened successfully, now listening for commands");
|
||||
|
||||
return true;
|
||||
|
||||
} catch (RemoteException e) {
|
||||
QLog.e(TAG, "openChannel: RemoteException while opening ANT+ Remote Control channel", e);
|
||||
isChannelOpen = false;
|
||||
return false;
|
||||
} catch (AntCommandFailedException e) {
|
||||
QLog.e(TAG, "openChannel: AntCommandFailedException while opening ANT+ Remote Control channel", e);
|
||||
isChannelOpen = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close ANT+ remote control channel
|
||||
*/
|
||||
public void closeChannel() {
|
||||
QLog.i(TAG, "closeChannel: request to close ANT+ Remote Control channel");
|
||||
|
||||
if (!isChannelOpen && mAntChannel == null) {
|
||||
QLog.d(TAG, "closeChannel: channel not open and null, nothing to do");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAntChannel == null) {
|
||||
QLog.w(TAG, "closeChannel: channel marked as open but mAntChannel is null, clearing flag");
|
||||
isChannelOpen = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
QLog.d(TAG, "closeChannel: closing ANT+ Remote Control channel");
|
||||
mAntChannel.close();
|
||||
QLog.d(TAG, "closeChannel: channel closed, releasing resources");
|
||||
mAntChannel.release();
|
||||
QLog.i(TAG, "closeChannel: ANT+ Remote Control channel closed and released successfully");
|
||||
} catch (RemoteException e) {
|
||||
QLog.e(TAG, "closeChannel: RemoteException while closing ANT+ Remote Control channel", e);
|
||||
} catch (AntCommandFailedException e) {
|
||||
QLog.e(TAG, "closeChannel: AntCommandFailedException while closing ANT+ Remote Control channel", e);
|
||||
}
|
||||
|
||||
isChannelOpen = false;
|
||||
mAntChannel = null;
|
||||
QLog.d(TAG, "closeChannel: cleanup completed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if channel is open
|
||||
*/
|
||||
public boolean isChannelOpen() {
|
||||
boolean channelOpen = isChannelOpen;
|
||||
QLog.v(TAG, "isChannelOpen: returning " + channelOpen);
|
||||
return channelOpen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the device number to search for (0 = wildcard)
|
||||
*/
|
||||
public void setDeviceNumber(int deviceNumber) {
|
||||
QLog.d(TAG, "setDeviceNumber: changing deviceNumber from " + this.deviceNumber + " to " + deviceNumber);
|
||||
if (deviceNumber == 0) {
|
||||
QLog.i(TAG, "setDeviceNumber: using wildcard (0) to accept any remote control");
|
||||
} else {
|
||||
QLog.i(TAG, "setDeviceNumber: will only accept remote control with device number " + deviceNumber);
|
||||
}
|
||||
this.deviceNumber = deviceNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current device number
|
||||
*/
|
||||
public int getDeviceNumber() {
|
||||
QLog.v(TAG, "getDeviceNumber: returning " + deviceNumber);
|
||||
return deviceNumber;
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,6 @@ public class ChannelService extends Service {
|
||||
SDMChannelController sdmChannelController = null;
|
||||
BikeChannelController bikeChannelController = null; // Added BikeChannelController reference
|
||||
BikeTransmitterController bikeTransmitterController = null; // Added BikeTransmitterController reference
|
||||
AntRemoteControl antRemoteControl = null; // Added AntRemoteControl reference
|
||||
|
||||
private ServiceConnection mAntRadioServiceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
@@ -308,41 +307,6 @@ public class ChannelService extends Service {
|
||||
return "Bike transmitter not initialized";
|
||||
}
|
||||
|
||||
// ========== REMOTE CONTROL METHODS ==========
|
||||
|
||||
/**
|
||||
* Check if remote control is connected
|
||||
*/
|
||||
boolean isRemoteControlConnected() {
|
||||
QLog.v(TAG, "ChannelServiceComm.isRemoteControlConnected");
|
||||
return (antRemoteControl != null && antRemoteControl.isChannelOpen());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the remote control device number (0 = wildcard)
|
||||
*/
|
||||
void setRemoteControlDeviceNumber(int deviceNumber) {
|
||||
QLog.v(TAG, "ChannelServiceComm.setRemoteControlDeviceNumber: " + deviceNumber);
|
||||
|
||||
if (antRemoteControl != null) {
|
||||
antRemoteControl.setDeviceNumber(deviceNumber);
|
||||
QLog.d(TAG, "Remote control device number updated to: " + deviceNumber);
|
||||
} else {
|
||||
QLog.w(TAG, "Remote control not initialized, cannot set device number");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get remote control status info for debugging
|
||||
*/
|
||||
String getRemoteControlInfo() {
|
||||
if (antRemoteControl != null) {
|
||||
return "Remote control initialized, channel open: " + antRemoteControl.isChannelOpen() +
|
||||
", device number: " + antRemoteControl.getDeviceNumber();
|
||||
}
|
||||
return "Remote control not initialized";
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes all channels currently added.
|
||||
*/
|
||||
@@ -429,37 +393,6 @@ public class ChannelService extends Service {
|
||||
bikeTransmitterController = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Add initialization for AntRemoteControl
|
||||
if (Ant.remoteControlRequest && antRemoteControl == null) {
|
||||
QLog.i(TAG, "Initializing AntRemoteControl");
|
||||
try {
|
||||
// Create remote control instance
|
||||
antRemoteControl = new AntRemoteControl();
|
||||
|
||||
// Set device number (0 = wildcard for any remote)
|
||||
antRemoteControl.setDeviceNumber(Ant.antRemoteControlDeviceNumber);
|
||||
|
||||
// Acquire channel like other controllers
|
||||
AntChannel remoteChannel = acquireChannel();
|
||||
if (remoteChannel != null) {
|
||||
boolean channelOpened = antRemoteControl.openChannel(remoteChannel);
|
||||
if (channelOpened) {
|
||||
QLog.i(TAG, "AntRemoteControl initialized and channel opened successfully");
|
||||
} else {
|
||||
QLog.e(TAG, "Failed to open AntRemoteControl channel");
|
||||
antRemoteControl = null;
|
||||
}
|
||||
} else {
|
||||
QLog.e(TAG, "Failed to acquire channel for AntRemoteControl");
|
||||
antRemoteControl = null;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
QLog.e(TAG, "Failed to initialize AntRemoteControl: " + e.getMessage(), e);
|
||||
antRemoteControl = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void closeAllChannels() {
|
||||
@@ -476,9 +409,6 @@ public class ChannelService extends Service {
|
||||
if (bikeTransmitterController != null) { // Added closing bikeTransmitterController
|
||||
bikeTransmitterController.close(); // Use close() method like other controllers
|
||||
}
|
||||
if (antRemoteControl != null) { // Added closing antRemoteControl
|
||||
antRemoteControl.closeChannel();
|
||||
}
|
||||
|
||||
heartChannelController = null;
|
||||
powerChannelController = null;
|
||||
@@ -486,7 +416,6 @@ public class ChannelService extends Service {
|
||||
sdmChannelController = null;
|
||||
bikeChannelController = null; // Added nullifying bikeChannelController
|
||||
bikeTransmitterController = null; // Added nullifying bikeTransmitterController
|
||||
antRemoteControl = null; // Added nullifying antRemoteControl
|
||||
}
|
||||
|
||||
AntChannel acquireChannel() throws ChannelNotAvailableException {
|
||||
|
||||
@@ -99,6 +99,10 @@ bluetooth::bluetooth(bool logs, const QString &deviceName, bool noWriteResistanc
|
||||
discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
|
||||
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &bluetooth::deviceDiscovered);
|
||||
|
||||
// Initialize Zwift device lists with "Auto" option
|
||||
zwiftClickDevicesList.append("Auto");
|
||||
zwiftPlayDevicesList.append("Auto");
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceUpdated, this, &bluetooth::deviceUpdated);
|
||||
|
||||
@@ -450,7 +454,8 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
|
||||
settings.value(QZSettings::toorx_srx_3500, QZSettings::default_toorx_srx_3500).toBool() ||
|
||||
settings.value(QZSettings::hop_sport_hs_090h_bike, QZSettings::default_hop_sport_hs_090h_bike).toBool() ||
|
||||
settings.value(QZSettings::toorx_bike_srx_500, QZSettings::default_toorx_bike_srx_500).toBool() ||
|
||||
settings.value(QZSettings::hertz_xr_770, QZSettings::default_hertz_xr_770).toBool()) &&
|
||||
settings.value(QZSettings::hertz_xr_770, QZSettings::default_hertz_xr_770).toBool() ||
|
||||
settings.value(QZSettings::taurua_ic90, QZSettings::default_taurua_ic90).toBool()) &&
|
||||
!toorx_ftms;
|
||||
bool snode_bike = settings.value(QZSettings::snode_bike, QZSettings::default_snode_bike).toBool();
|
||||
bool fitplus_bike = settings.value(QZSettings::fitplus_bike, QZSettings::default_fitplus_bike).toBool() ||
|
||||
@@ -643,6 +648,27 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
|
||||
}
|
||||
if (!found) {
|
||||
devices.append(device);
|
||||
|
||||
// Cache Zwift devices for ComboBox selection
|
||||
QString deviceName = device.name().toUpper();
|
||||
#if defined(Q_OS_DARWIN) || defined(Q_OS_IOS)
|
||||
QString deviceAddress = device.deviceUuid().toString();
|
||||
#else
|
||||
QString deviceAddress = device.address().toString();
|
||||
#endif
|
||||
QString deviceDisplay = device.name() + " (" + deviceAddress + ")";
|
||||
|
||||
if (deviceName.startsWith("ZWIFT CLICK")) {
|
||||
if (!zwiftClickDevicesList.contains(deviceDisplay)) {
|
||||
zwiftClickDevicesList.append(deviceDisplay);
|
||||
emit zwiftClickDevicesChanged();
|
||||
}
|
||||
} else if (deviceName.startsWith("ZWIFT PLAY") || deviceName.startsWith("ZWIFT RIDE") || deviceName.startsWith("ZWIFT SF2")) {
|
||||
if (!zwiftPlayDevicesList.contains(deviceDisplay)) {
|
||||
zwiftPlayDevicesList.append(deviceDisplay);
|
||||
emit zwiftPlayDevicesChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3010,10 +3036,24 @@ void bluetooth::connectedAndDiscovered() {
|
||||
}
|
||||
|
||||
if(settings.value(QZSettings::zwift_click, QZSettings::default_zwift_click).toBool()) {
|
||||
QString zwiftClickName = settings.value(QZSettings::zwift_click_name, QZSettings::default_zwift_click_name).toString();
|
||||
for (const QBluetoothDeviceInfo &b : qAsConst(devices)) {
|
||||
if (((b.name().toUpper().startsWith("ZWIFT CLICK"))) && !zwiftClickRemote && this->device() &&
|
||||
this->device()->deviceType() == bluetoothdevice::BIKE) {
|
||||
|
||||
// Check MAC address filter if not "Auto"
|
||||
if (zwiftClickName != "Auto") {
|
||||
#if defined(Q_OS_DARWIN) || defined(Q_OS_IOS)
|
||||
QString deviceAddress = b.deviceUuid().toString();
|
||||
#else
|
||||
QString deviceAddress = b.address().toString();
|
||||
#endif
|
||||
QString deviceDisplay = b.name() + " (" + deviceAddress + ")";
|
||||
if (deviceDisplay != zwiftClickName) {
|
||||
continue; // Skip this device if it doesn't match the selected one
|
||||
}
|
||||
}
|
||||
|
||||
if(b.manufacturerData(2378).size() > 0) {
|
||||
qDebug() << "this should be 9. is it? " << int(b.manufacturerData(2378).at(0));
|
||||
} else {
|
||||
@@ -3055,20 +3095,49 @@ void bluetooth::connectedAndDiscovered() {
|
||||
|
||||
if(settings.value(QZSettings::zwift_play, QZSettings::default_zwift_play).toBool()) {
|
||||
bool zwiftplay_swap = settings.value(QZSettings::zwiftplay_swap, QZSettings::default_zwiftplay_swap).toBool();
|
||||
QString zwiftPlayLeftName = settings.value(QZSettings::zwift_play_left_name, QZSettings::default_zwift_play_left_name).toString();
|
||||
QString zwiftPlayRightName = settings.value(QZSettings::zwift_play_right_name, QZSettings::default_zwift_play_right_name).toString();
|
||||
|
||||
for (const QBluetoothDeviceInfo &b : qAsConst(devices)) {
|
||||
if ((((b.name().toUpper().startsWith("ZWIFT PLAY"))) || b.name().toUpper().startsWith("ZWIFT RIDE") || b.name().toUpper().startsWith("ZWIFT SF2")) && zwiftPlayDevice.size() < 2 && this->device() &&
|
||||
this->device()->deviceType() == bluetoothdevice::BIKE) {
|
||||
|
||||
// Determine if this is LEFT or RIGHT device
|
||||
AbstractZapDevice::ZWIFT_PLAY_TYPE deviceType = AbstractZapDevice::ZWIFT_PLAY_TYPE::NONE;
|
||||
if(b.manufacturerData(2378).size() > 0) {
|
||||
deviceType = (int(b.manufacturerData(2378).at(0)) == 3 || int(b.manufacturerData(2378).at(0)) == 7) ?
|
||||
AbstractZapDevice::ZWIFT_PLAY_TYPE::LEFT : AbstractZapDevice::ZWIFT_PLAY_TYPE::RIGHT;
|
||||
} else {
|
||||
deviceType = (zwiftPlayDevice.length() == 0) ? AbstractZapDevice::ZWIFT_PLAY_TYPE::LEFT : AbstractZapDevice::ZWIFT_PLAY_TYPE::RIGHT;
|
||||
}
|
||||
|
||||
// Check MAC address filter based on device type
|
||||
bool shouldConnect = true;
|
||||
QString selectedDevice = (deviceType == AbstractZapDevice::ZWIFT_PLAY_TYPE::LEFT) ? zwiftPlayLeftName : zwiftPlayRightName;
|
||||
|
||||
if (selectedDevice != "Auto") {
|
||||
#if defined(Q_OS_DARWIN) || defined(Q_OS_IOS)
|
||||
QString deviceAddress = b.deviceUuid().toString();
|
||||
#else
|
||||
QString deviceAddress = b.address().toString();
|
||||
#endif
|
||||
QString deviceDisplay = b.name() + " (" + deviceAddress + ")";
|
||||
if (deviceDisplay != selectedDevice) {
|
||||
shouldConnect = false; // Skip this device if it doesn't match the selected one
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldConnect) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(b.manufacturerData(2378).size() > 0) {
|
||||
qDebug() << "this should be 3 or 2. is it? " << int(b.manufacturerData(2378).at(0));
|
||||
zwiftPlayDevice.append(new zwiftclickremote(this->device(),
|
||||
int(b.manufacturerData(2378).at(0)) == 3 || int(b.manufacturerData(2378).at(0)) == 7 ? AbstractZapDevice::ZWIFT_PLAY_TYPE::LEFT : AbstractZapDevice::ZWIFT_PLAY_TYPE::RIGHT));
|
||||
} else {
|
||||
qDebug() << "manufacturer not found for ZWIFT CLICK";
|
||||
zwiftPlayDevice.append(new zwiftclickremote(this->device(),
|
||||
zwiftPlayDevice.length() == 0 ? AbstractZapDevice::ZWIFT_PLAY_TYPE::LEFT : AbstractZapDevice::ZWIFT_PLAY_TYPE::RIGHT));
|
||||
|
||||
}
|
||||
|
||||
zwiftPlayDevice.append(new zwiftclickremote(this->device(), deviceType));
|
||||
// connect(heartRateBelt, SIGNAL(disconnected()), this, SLOT(restart()));
|
||||
|
||||
connect(zwiftPlayDevice.last(), &zwiftclickremote::debug, this, &bluetooth::debug);
|
||||
@@ -4182,3 +4251,11 @@ void bluetooth::deviceUpdated(const QBluetoothDeviceInfo &device, QBluetoothDevi
|
||||
debug("deviceUpdated " + device.name() + " " + updateFields);
|
||||
}
|
||||
#endif
|
||||
|
||||
QStringList bluetooth::getZwiftClickDevices() const {
|
||||
return zwiftClickDevicesList;
|
||||
}
|
||||
|
||||
QStringList bluetooth::getZwiftPlayDevices() const {
|
||||
return zwiftPlayDevicesList;
|
||||
}
|
||||
|
||||
@@ -161,6 +161,8 @@
|
||||
class bluetooth : public QObject, public SignalHandler {
|
||||
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QStringList zwiftClickDevices READ getZwiftClickDevices NOTIFY zwiftClickDevicesChanged)
|
||||
Q_PROPERTY(QStringList zwiftPlayDevices READ getZwiftPlayDevices NOTIFY zwiftPlayDevicesChanged)
|
||||
public:
|
||||
bluetooth(const discoveryoptions &options);
|
||||
explicit bluetooth(bool logs, const QString &deviceName = QLatin1String(""), bool noWriteResistance = false,
|
||||
@@ -175,6 +177,9 @@ class bluetooth : public QObject, public SignalHandler {
|
||||
bool onlyDiscover = false;
|
||||
volatile bool homeformLoaded = false;
|
||||
|
||||
QStringList getZwiftClickDevices() const;
|
||||
QStringList getZwiftPlayDevices() const;
|
||||
|
||||
private:
|
||||
bool useDiscovery = false;
|
||||
QFile *debugCommsLog = nullptr;
|
||||
@@ -308,6 +313,10 @@ class bluetooth : public QObject, public SignalHandler {
|
||||
elitesquarecontroller* eliteSquareController = nullptr;
|
||||
QString filterDevice = QLatin1String("");
|
||||
|
||||
// Device discovery lists for Zwift devices
|
||||
QStringList zwiftClickDevicesList;
|
||||
QStringList zwiftPlayDevicesList;
|
||||
|
||||
bool testResistance = false;
|
||||
bool noWriteResistance = false;
|
||||
bool noHeartService = false;
|
||||
@@ -365,6 +374,8 @@ class bluetooth : public QObject, public SignalHandler {
|
||||
|
||||
void bluetoothDeviceConnected(bluetoothdevice *b);
|
||||
void bluetoothDeviceDisconnected();
|
||||
void zwiftClickDevicesChanged();
|
||||
void zwiftPlayDevicesChanged();
|
||||
public slots:
|
||||
void restart();
|
||||
void debug(const QString &string);
|
||||
|
||||
@@ -290,6 +290,94 @@ void proformbike::forceResistance(resistance_t requestResistance) {
|
||||
uint8_t noOpData7[] = {0xfe, 0x02, 0x0d, 0x02};
|
||||
writeCharacteristic((uint8_t *)noOpData7, sizeof(noOpData7), QStringLiteral("resrequest"), false, false);
|
||||
|
||||
switch (requestResistance) {
|
||||
case 1:
|
||||
writeCharacteristic((uint8_t *)res1, sizeof(res1), QStringLiteral("resistance1"), false, true);
|
||||
break;
|
||||
case 2:
|
||||
writeCharacteristic((uint8_t *)res2, sizeof(res2), QStringLiteral("resistance2"), false, true);
|
||||
break;
|
||||
case 3:
|
||||
writeCharacteristic((uint8_t *)res3, sizeof(res3), QStringLiteral("resistance3"), false, true);
|
||||
break;
|
||||
case 4:
|
||||
writeCharacteristic((uint8_t *)res4, sizeof(res4), QStringLiteral("resistance4"), false, true);
|
||||
break;
|
||||
case 5:
|
||||
writeCharacteristic((uint8_t *)res5, sizeof(res5), QStringLiteral("resistance5"), false, true);
|
||||
break;
|
||||
case 6:
|
||||
writeCharacteristic((uint8_t *)res6, sizeof(res6), QStringLiteral("resistance6"), false, true);
|
||||
break;
|
||||
case 7:
|
||||
writeCharacteristic((uint8_t *)res7, sizeof(res7), QStringLiteral("resistance7"), false, true);
|
||||
break;
|
||||
case 8:
|
||||
writeCharacteristic((uint8_t *)res8, sizeof(res8), QStringLiteral("resistance8"), false, true);
|
||||
break;
|
||||
case 9:
|
||||
writeCharacteristic((uint8_t *)res9, sizeof(res9), QStringLiteral("resistance9"), false, true);
|
||||
break;
|
||||
case 10:
|
||||
writeCharacteristic((uint8_t *)res10, sizeof(res10), QStringLiteral("resistance10"), false, true);
|
||||
break;
|
||||
case 11:
|
||||
writeCharacteristic((uint8_t *)res11, sizeof(res11), QStringLiteral("resistance11"), false, true);
|
||||
break;
|
||||
case 12:
|
||||
writeCharacteristic((uint8_t *)res12, sizeof(res12), QStringLiteral("resistance12"), false, true);
|
||||
break;
|
||||
case 13:
|
||||
writeCharacteristic((uint8_t *)res13, sizeof(res13), QStringLiteral("resistance13"), false, true);
|
||||
break;
|
||||
case 14:
|
||||
writeCharacteristic((uint8_t *)res14, sizeof(res14), QStringLiteral("resistance14"), false, true);
|
||||
break;
|
||||
case 15:
|
||||
writeCharacteristic((uint8_t *)res15, sizeof(res15), QStringLiteral("resistance15"), false, true);
|
||||
break;
|
||||
case 16:
|
||||
writeCharacteristic((uint8_t *)res16, sizeof(res16), QStringLiteral("resistance16"), false, true);
|
||||
break;
|
||||
}
|
||||
} else if (proform_csx210) {
|
||||
// ProForm CSX210 specific resistance frames (1-16)
|
||||
const uint8_t res1[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x02,
|
||||
0x00, 0x10, 0x01, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res2[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x02,
|
||||
0x00, 0x10, 0x03, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res3[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0x52, 0x07, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res4[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0xc3, 0x09, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res5[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0x34, 0x0c, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res6[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0xa5, 0x0e, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res7[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0x16, 0x11, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res8[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0x87, 0x13, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res9[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0xf8, 0x15, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res10[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0x69, 0x18, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res11[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0xda, 0x1a, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res12[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0x4b, 0x1d, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res13[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0xbc, 0x1f, 0x00, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res14[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0x2d, 0x22, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res15[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0x9e, 0x24, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t res16[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01,
|
||||
0x04, 0x0f, 0x27, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
uint8_t noOpData7[] = {0xfe, 0x02, 0x0d, 0x02};
|
||||
writeCharacteristic((uint8_t *)noOpData7, sizeof(noOpData7), QStringLiteral("resrequest"), false, false);
|
||||
|
||||
switch (requestResistance) {
|
||||
case 1:
|
||||
writeCharacteristic((uint8_t *)res1, sizeof(res1), QStringLiteral("resistance1"), false, true);
|
||||
@@ -895,10 +983,24 @@ void proformbike::update() {
|
||||
uint8_t noOpData5_proform_xbike[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x00,
|
||||
0x03, 0x80, 0x00, 0x40, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// proform_csx210
|
||||
uint8_t noOpData1_proform_csx210[] = {0xfe, 0x02, 0x17, 0x03};
|
||||
uint8_t noOpData2_proform_csx210[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x00,
|
||||
0x0d, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t noOpData3_proform_csx210[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x10, 0xb9, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t noOpData4_proform_csx210[] = {0xfe, 0x02, 0x17, 0x03};
|
||||
uint8_t noOpData5_proform_csx210[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x00,
|
||||
0x0d, 0x3c, 0x96, 0x71, 0x00, 0x10, 0x40, 0x40, 0x00, 0x80};
|
||||
uint8_t noOpData6_proform_csx210[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x81, 0xfd, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
|
||||
switch (counterPoll) {
|
||||
case 0:
|
||||
if (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci || proform_hybrid_trainer_PFEL03815 || proform_bike_sb || proform_bike_225_csx || proform_bike_325_csx || proform_xbike || proform_225_csx_PFEX32925_INT_0) {
|
||||
if (proform_csx210) {
|
||||
writeCharacteristic(noOpData1_proform_csx210, sizeof(noOpData1_proform_csx210), QStringLiteral("noOp"));
|
||||
} else if (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci || proform_hybrid_trainer_PFEL03815 || proform_bike_sb || proform_bike_225_csx || proform_bike_325_csx || proform_xbike || proform_225_csx_PFEX32925_INT_0) {
|
||||
writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp"));
|
||||
} else if(proform_bike_PFEVEX71316_0) {
|
||||
writeCharacteristic(noOpData1_proform_bike_PFEVEX71316_0, sizeof(noOpData1_proform_bike_PFEVEX71316_0), QStringLiteral("noOp"));
|
||||
@@ -907,7 +1009,9 @@ void proformbike::update() {
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (proform_xbike) {
|
||||
if (proform_csx210) {
|
||||
writeCharacteristic(noOpData2_proform_csx210, sizeof(noOpData2_proform_csx210), QStringLiteral("noOp"));
|
||||
} else if (proform_xbike) {
|
||||
writeCharacteristic(noOpData2_proform_xbike, sizeof(noOpData2_proform_xbike), QStringLiteral("noOp"));
|
||||
} else if (proform_studio || proform_tdf_10)
|
||||
writeCharacteristic(noOpData2_proform_studio, sizeof(noOpData2_proform_studio), QStringLiteral("noOp"));
|
||||
@@ -941,7 +1045,9 @@ void proformbike::update() {
|
||||
writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("noOp"));
|
||||
break;
|
||||
case 2:
|
||||
if (proform_xbike) {
|
||||
if (proform_csx210) {
|
||||
writeCharacteristic(noOpData3_proform_csx210, sizeof(noOpData3_proform_csx210), QStringLiteral("noOp"));
|
||||
} else if (proform_xbike) {
|
||||
writeCharacteristic(noOpData3_proform_xbike, sizeof(noOpData3_proform_xbike), QStringLiteral("noOp"));
|
||||
} else if (proform_studio || proform_tdf_10)
|
||||
writeCharacteristic(noOpData3_proform_studio, sizeof(noOpData3_proform_studio), QStringLiteral("noOp"));
|
||||
@@ -975,7 +1081,9 @@ void proformbike::update() {
|
||||
writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("noOp"));
|
||||
break;
|
||||
case 3:
|
||||
if (proform_xbike) {
|
||||
if (proform_csx210) {
|
||||
writeCharacteristic(noOpData4_proform_csx210, sizeof(noOpData4_proform_csx210), QStringLiteral("noOp"));
|
||||
} else if (proform_xbike) {
|
||||
innerWriteResistance();
|
||||
writeCharacteristic(noOpData7, sizeof(noOpData7), QStringLiteral("noOp"));
|
||||
} else if (proform_studio || proform_tdf_10)
|
||||
@@ -998,7 +1106,9 @@ void proformbike::update() {
|
||||
writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp"));
|
||||
break;
|
||||
case 4:
|
||||
if (proform_xbike) {
|
||||
if (proform_csx210) {
|
||||
writeCharacteristic(noOpData5_proform_csx210, sizeof(noOpData5_proform_csx210), QStringLiteral("noOp"));
|
||||
} else if (proform_xbike) {
|
||||
writeCharacteristic(noOpData5_proform_xbike, sizeof(noOpData5_proform_xbike), QStringLiteral("noOp"));
|
||||
} else if (proform_studio || proform_tdf_10)
|
||||
writeCharacteristic(noOpData5_proform_studio, sizeof(noOpData5_proform_studio), QStringLiteral("noOp"));
|
||||
@@ -1026,7 +1136,9 @@ void proformbike::update() {
|
||||
writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("noOp"));
|
||||
break;
|
||||
case 5:
|
||||
if (proform_studio || proform_tdf_10)
|
||||
if (proform_csx210) {
|
||||
writeCharacteristic(noOpData6_proform_csx210, sizeof(noOpData6_proform_csx210), QStringLiteral("noOp"));
|
||||
} else if (proform_studio || proform_tdf_10)
|
||||
writeCharacteristic(noOpData6_proform_studio, sizeof(noOpData6_proform_studio), QStringLiteral("noOp"));
|
||||
else if (proform_tour_de_france_clc) {
|
||||
writeCharacteristic(noOpData6_proform_tour_de_france_clc, sizeof(noOpData6_proform_tour_de_france_clc),
|
||||
@@ -1089,7 +1201,7 @@ void proformbike::update() {
|
||||
requestResistance == -1) {
|
||||
// this bike sends the frame noOpData7 only when it needs to change the resistance
|
||||
counterPoll = 0;
|
||||
} else if (counterPoll == 5 && (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci || proform_hybrid_trainer_PFEL03815 || proform_bike_sb || proform_bike_325_csx || proform_xbike)) {
|
||||
} else if (counterPoll == 5 && (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci || proform_hybrid_trainer_PFEL03815 || proform_bike_sb || proform_bike_325_csx || proform_xbike || proform_csx210)) {
|
||||
counterPoll = 0;
|
||||
}
|
||||
|
||||
@@ -1967,10 +2079,13 @@ void proformbike::btinit() {
|
||||
proform_bike_PFEVEX71316_0 = settings.value(QZSettings::proform_bike_PFEVEX71316_0, QZSettings::default_proform_bike_PFEVEX71316_0).toBool();
|
||||
proform_xbike = settings.value(QZSettings::proform_xbike, QZSettings::default_proform_xbike).toBool();
|
||||
proform_225_csx_PFEX32925_INT_0 = settings.value(QZSettings::proform_225_csx_PFEX32925_INT_0, QZSettings::default_proform_225_csx_PFEX32925_INT_0).toBool();
|
||||
proform_csx210 = settings.value(QZSettings::proform_csx210, QZSettings::default_proform_csx210).toBool();
|
||||
|
||||
|
||||
if(nordictrack_GX4_5_bike)
|
||||
max_resistance = 25;
|
||||
if(proform_csx210)
|
||||
max_resistance = 16;
|
||||
|
||||
if (settings.value(QZSettings::proform_studio, QZSettings::default_proform_studio).toBool()) {
|
||||
|
||||
@@ -2940,6 +3055,178 @@ void proformbike::btinit() {
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
} else if (proform_csx210) {
|
||||
// ProForm CSX210 initialization sequence with 16 max resistance
|
||||
|
||||
uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02};
|
||||
uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData3[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x07, 0x04, 0x80, 0x8b,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData4[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x07, 0x04, 0x88, 0x93,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData5[] = {0xfe, 0x02, 0x0b, 0x02};
|
||||
uint8_t initData6[] = {0xff, 0x0b, 0x02, 0x04, 0x02, 0x07, 0x02, 0x07, 0x82, 0x00,
|
||||
0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData7[] = {0xfe, 0x02, 0x0a, 0x02};
|
||||
uint8_t initData8[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x84, 0x00,
|
||||
0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData9[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x95, 0x9b,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData10[] = {0xfe, 0x02, 0x2c, 0x04};
|
||||
|
||||
// Execute initial setup sequence
|
||||
writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData2, sizeof(initData2), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData3, sizeof(initData3), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData4, sizeof(initData4), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData5, sizeof(initData5), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData6, sizeof(initData6), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData7, sizeof(initData7), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData8, sizeof(initData8), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData9, sizeof(initData9), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData10, sizeof(initData10), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
|
||||
// Main initialization sequence
|
||||
uint8_t initData11[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x07, 0x28, 0x90, 0x04,
|
||||
0x00, 0xb2, 0xf4, 0x34, 0x72, 0xbe, 0x08, 0x40, 0x9e, 0xea};
|
||||
uint8_t initData12[] = {0x01, 0x12, 0x3c, 0x8c, 0xda, 0x26, 0x90, 0xc8, 0x26, 0x82,
|
||||
0xe4, 0x44, 0xa2, 0x0e, 0x98, 0xf0, 0x4e, 0xda, 0x2c, 0xbc};
|
||||
uint8_t initData13[] = {0xff, 0x08, 0x0a, 0x96, 0x20, 0x80, 0x02, 0x00, 0x00, 0x17,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData13, sizeof(initData13), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
|
||||
// Service discovery and configuration sequence
|
||||
uint8_t initData14[] = {0xfe, 0x02, 0x19, 0x03};
|
||||
uint8_t initData15[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x07, 0x15, 0x02, 0x0e,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData16[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x3d, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData17[] = {0xfe, 0x02, 0x17, 0x03};
|
||||
uint8_t initData18[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x0c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData19[] = {0xff, 0x05, 0x00, 0x80, 0x01, 0x00, 0xa9, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData20[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x00,
|
||||
0x0d, 0x00, 0x10, 0x00, 0xc0, 0x1c, 0x4c, 0x00, 0x00, 0xe0};
|
||||
uint8_t initData21[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x10, 0x51, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
writeCharacteristic(initData14, sizeof(initData14), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData15, sizeof(initData15), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData16, sizeof(initData16), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData17, sizeof(initData17), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData18, sizeof(initData18), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData19, sizeof(initData19), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData17, sizeof(initData17), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData20, sizeof(initData20), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData21, sizeof(initData21), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
|
||||
// Additional configuration and status frames
|
||||
uint8_t initData22[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x00,
|
||||
0x0d, 0x3c, 0x96, 0x71, 0x00, 0x10, 0x40, 0x40, 0x00, 0x80};
|
||||
uint8_t initData23[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x81, 0xfd, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData24[] = {0xfe, 0x02, 0x11, 0x02};
|
||||
uint8_t initData25[] = {0xff, 0x11, 0x02, 0x04, 0x02, 0x0d, 0x07, 0x0d, 0x02, 0x05,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x58, 0x02, 0x00, 0x7d, 0x00};
|
||||
|
||||
writeCharacteristic(initData17, sizeof(initData17), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData22, sizeof(initData22), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData23, sizeof(initData23), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData24, sizeof(initData24), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData25, sizeof(initData25), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
|
||||
// Final status and configuration frames
|
||||
uint8_t initData26[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x00,
|
||||
0x0d, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData27[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x10, 0xb9, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData28[] = {0xfe, 0x02, 0x10, 0x02};
|
||||
uint8_t initData29[] = {0xff, 0x10, 0x02, 0x04, 0x02, 0x0c, 0x07, 0x0c, 0x02, 0x04,
|
||||
0x00, 0x00, 0x00, 0x02, 0x98, 0x21, 0x00, 0xd4, 0x00, 0x00};
|
||||
uint8_t initData30[] = {0xfe, 0x02, 0x10, 0x02};
|
||||
uint8_t initData31[] = {0xff, 0x10, 0x02, 0x04, 0x02, 0x0c, 0x07, 0x0c, 0x02, 0x05,
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x2b, 0x00, 0x00};
|
||||
uint8_t initData32[] = {0xfe, 0x02, 0x17, 0x03};
|
||||
uint8_t initData33[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x0c,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData34[] = {0xff, 0x05, 0x00, 0x80, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t initData35[] = {0xfe, 0x02, 0x17, 0x03};
|
||||
uint8_t initData36[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x00,
|
||||
0x0d, 0x3c, 0x96, 0x71, 0x00, 0x10, 0x40, 0x40, 0x00, 0x80};
|
||||
uint8_t initData37[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x81, 0xfd, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
writeCharacteristic(initData14, sizeof(initData14), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData15, sizeof(initData15), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData16, sizeof(initData16), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData28, sizeof(initData28), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData29, sizeof(initData29), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData17, sizeof(initData17), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData26, sizeof(initData26), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData27, sizeof(initData27), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData30, sizeof(initData30), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData31, sizeof(initData31), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData32, sizeof(initData32), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData33, sizeof(initData33), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData34, sizeof(initData34), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData35, sizeof(initData35), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData36, sizeof(initData36), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData37, sizeof(initData37), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
} else {
|
||||
|
||||
uint8_t initData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x07, 0x28, 0x90, 0x07,
|
||||
|
||||
@@ -96,6 +96,7 @@ class proformbike : public bike {
|
||||
bool proform_bike_PFEVEX71316_0 = false;
|
||||
bool proform_xbike = false;
|
||||
bool proform_225_csx_PFEX32925_INT_0 = false;
|
||||
bool proform_csx210 = false;
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
lockscreen *h = 0;
|
||||
|
||||
@@ -186,6 +186,10 @@ void trxappgateusbbike::update() {
|
||||
noOpData[4] = crc;
|
||||
pollCounter += 0x0c;
|
||||
writeCharacteristic((uint8_t *)noOpData, sizeof(noOpData), QStringLiteral("noOp"), false, true);
|
||||
} else if (bike_type == TYPE::TAURUA_IC90) {
|
||||
|
||||
const uint8_t noOpData[] = {0xf0, 0xa2, 0x01, 0x31, 0xc4};
|
||||
writeCharacteristic((uint8_t *)noOpData, sizeof(noOpData), QStringLiteral("noOp"), false, true);
|
||||
} else {
|
||||
|
||||
const uint8_t noOpData[] = {0xf0, 0xa2, 0x23, 0xd3, 0x88};
|
||||
@@ -817,6 +821,24 @@ void trxappgateusbbike::btinit(bool startTape) {
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic((uint8_t *)initData8, sizeof(initData8), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(400);
|
||||
} else if (bike_type == TYPE::TAURUA_IC90) {
|
||||
const uint8_t initData1[] = {0xf0, 0xa0, 0x01, 0x00, 0x91};
|
||||
const uint8_t initData2[] = {0xf0, 0xa0, 0x01, 0x31, 0xc2};
|
||||
const uint8_t initData3[] = {0xf0, 0xa1, 0x01, 0x31, 0xc3};
|
||||
const uint8_t initData4[] = {0xf0, 0xa0, 0x01, 0x31, 0xc2};
|
||||
const uint8_t initData5[] = {0xf0, 0xa1, 0x01, 0x31, 0xc3};
|
||||
const uint8_t initData6[] = {0xf0, 0xa3, 0x01, 0x31, 0x01, 0xc6};
|
||||
const uint8_t initData7[] = {0xf0, 0xa4, 0x01, 0x31, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xd0};
|
||||
const uint8_t initData8[] = {0xf0, 0xa5, 0x01, 0x31, 0x02, 0xc9};
|
||||
|
||||
writeCharacteristic((uint8_t *)initData1, sizeof(initData1), QStringLiteral("init"), false, true);
|
||||
writeCharacteristic((uint8_t *)initData2, sizeof(initData2), QStringLiteral("init"), false, true);
|
||||
writeCharacteristic((uint8_t *)initData3, sizeof(initData3), QStringLiteral("init"), false, true);
|
||||
writeCharacteristic((uint8_t *)initData4, sizeof(initData4), QStringLiteral("init"), false, true);
|
||||
writeCharacteristic((uint8_t *)initData5, sizeof(initData5), QStringLiteral("init"), false, true);
|
||||
writeCharacteristic((uint8_t *)initData6, sizeof(initData6), QStringLiteral("init"), false, true);
|
||||
writeCharacteristic((uint8_t *)initData7, sizeof(initData7), QStringLiteral("init"), false, true);
|
||||
writeCharacteristic((uint8_t *)initData8, sizeof(initData8), QStringLiteral("init"), false, true);
|
||||
} else {
|
||||
|
||||
const uint8_t initData1[] = {0xf0, 0xa0, 0x01, 0x01, 0x92};
|
||||
@@ -1104,6 +1126,7 @@ void trxappgateusbbike::deviceDiscovered(const QBluetoothDeviceInfo &device) {
|
||||
bool enerfit_SPX_9500 = settings.value(QZSettings::enerfit_SPX_9500, QZSettings::default_enerfit_SPX_9500).toBool();
|
||||
bool hop_sport_hs_090h_bike = settings.value(QZSettings::hop_sport_hs_090h_bike, QZSettings::default_hop_sport_hs_090h_bike).toBool();
|
||||
bool toorx_bike_srx_500 = settings.value(QZSettings::toorx_bike_srx_500, QZSettings::default_toorx_bike_srx_500).toBool();
|
||||
bool taurua_ic90 = settings.value(QZSettings::taurua_ic90, QZSettings::default_taurua_ic90).toBool();
|
||||
emit debug(QStringLiteral("Found new device: ") + device.name() + QStringLiteral(" (") +
|
||||
device.address().toString() + ')');
|
||||
// if(device.name().startsWith("TOORX") || device.name().startsWith("V-RUN") || device.name().startsWith("FS-")
|
||||
@@ -1153,6 +1176,11 @@ void trxappgateusbbike::deviceDiscovered(const QBluetoothDeviceInfo &device) {
|
||||
|
||||
bike_type = TYPE::TOORX_SRX_500;
|
||||
qDebug() << QStringLiteral("TOORX_SRX_500 bike found");
|
||||
} else if(taurua_ic90) {
|
||||
refresh->start(500ms);
|
||||
|
||||
bike_type = TYPE::TAURUA_IC90;
|
||||
qDebug() << QStringLiteral("TAURUA_IC90 bike found");
|
||||
} else if (device.name().toUpper().startsWith(QStringLiteral("REEBOK"))) {
|
||||
bike_type = TYPE::REEBOK;
|
||||
qDebug() << QStringLiteral("REEBOK bike found");
|
||||
|
||||
@@ -116,6 +116,7 @@ class trxappgateusbbike : public bike {
|
||||
PASYOU = 27,
|
||||
FAL_SPORTS = 28,
|
||||
HAMMER_SPEED_BIKE_S = 29,
|
||||
TAURUA_IC90 = 30,
|
||||
} TYPE;
|
||||
TYPE bike_type = TRXAPPGATE;
|
||||
|
||||
|
||||
@@ -331,7 +331,7 @@ void wahookickrsnapbike::update() {
|
||||
}
|
||||
|
||||
auto virtualBike = this->VirtualBike();
|
||||
if (requestResistance != currentResistance().value() &&
|
||||
if (requestResistance != currentResistance().value() && requestResistance != -1 &&
|
||||
((virtualBike && !virtualBike->ftmsDeviceConnected()) || !virtualBike)) {
|
||||
emit debug(QStringLiteral("writing resistance ") + QString::number(requestResistance));
|
||||
lastForcedResistance = requestResistance;
|
||||
@@ -341,11 +341,14 @@ void wahookickrsnapbike::update() {
|
||||
writeCharacteristic(b, a.length(), "setResistance", false, false);
|
||||
} else if (requestResistance != currentResistance().value() &&
|
||||
((virtualBike && !virtualBike->ftmsDeviceConnected()) || !virtualBike) && lastGearValue != gears()) {
|
||||
emit debug(QStringLiteral("writing resistance due to gears changed ") + QString::number(lastForcedResistance));
|
||||
QByteArray a = setResistanceMode(((double)lastForcedResistance + (gears() - lastGearValue)) / 100.0);
|
||||
uint8_t b[20];
|
||||
memcpy(b, a.constData(), a.length());
|
||||
writeCharacteristic(b, a.length(), "setResistance", false, false);
|
||||
emit debug(QStringLiteral("writing resistance due to gears changed ") + QString::number(lastForcedResistance));
|
||||
if(lastForcedResistance == -1)
|
||||
lastForcedResistance = 1;
|
||||
lastForcedResistance = ((double)lastForcedResistance + (gears() - lastGearValue));
|
||||
QByteArray a = setResistanceMode(lastForcedResistance / 100.0);
|
||||
uint8_t b[20];
|
||||
memcpy(b, a.constData(), a.length());
|
||||
writeCharacteristic(b, a.length(), "setResistance", false, false);
|
||||
} else if (virtualBike && virtualBike->ftmsDeviceConnected() && lastGearValue != gears()) {
|
||||
inclinationChanged(lastGrade, lastGrade);
|
||||
}
|
||||
|
||||
183
src/qdomyos-zwift.pro.user.568050d
Normal file
183
src/qdomyos-zwift.pro.user.568050d
Normal file
@@ -0,0 +1,183 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 6.0.2, 2025-08-20T15:38:07. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{568050d7-c503-4fc0-9ae4-06a869edadb0}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey"/>
|
||||
<value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
|
||||
<value type="QString" key="ClangCodeModel.WarningConfigId">Builtin.BuildSystem</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">4</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{2eb206bb-7c50-4d71-9631-4ca0a2afd6d4}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/cagnulein/qdomyos-zwift/build-qdomyos-zwift-Desktop-Release</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/home/cagnulein/qdomyos-zwift/build-qdomyos-zwift-Desktop-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="int" key="QtQuickCompiler">1</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/cagnulein/qdomyos-zwift/src/qdomyos-zwift.pro</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/home/cagnulein/qdomyos-zwift/src/qdomyos-zwift.pro</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/cagnulein/qdomyos-zwift/build-qdomyos-zwift-Desktop-Release</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
@@ -685,8 +685,6 @@ const QString QZSettings::ftms_treadmill = QStringLiteral("ftms_treadmill");
|
||||
const QString QZSettings::default_ftms_treadmill = QStringLiteral("Disabled");
|
||||
const QString QZSettings::ant_speed_offset = QStringLiteral("ant_speed_offset");
|
||||
const QString QZSettings::ant_speed_gain = QStringLiteral("ant_speed_gain");
|
||||
const QString QZSettings::ant_remote_control = QStringLiteral("ant_remote_control");
|
||||
const QString QZSettings::ant_remote_control_device_number = QStringLiteral("ant_remote_control_device_number");
|
||||
const QString QZSettings::proform_rower_sport_rl = QStringLiteral("proform_rower_sport_rl");
|
||||
const QString QZSettings::strava_date_prefix = QStringLiteral("strava_date_prefix");
|
||||
const QString QZSettings::race_mode = QStringLiteral("race_mode");
|
||||
@@ -983,9 +981,17 @@ const QString QZSettings::chart_display_mode = QStringLiteral("chart_display_mod
|
||||
const QString QZSettings::calories_active_only = QStringLiteral("calories_active_only");
|
||||
const QString QZSettings::calories_from_hr = QStringLiteral("calories_from_hr");
|
||||
const QString QZSettings::height = QStringLiteral("height");
|
||||
const QString QZSettings::taurua_ic90 = QStringLiteral("taurua_ic90");
|
||||
const QString QZSettings::proform_csx210 = QStringLiteral("proform_csx210");
|
||||
const QString QZSettings::zwift_click_name = QStringLiteral("zwift_click_name");
|
||||
const QString QZSettings::default_zwift_click_name = QStringLiteral("Auto");
|
||||
const QString QZSettings::zwift_play_left_name = QStringLiteral("zwift_play_left_name");
|
||||
const QString QZSettings::default_zwift_play_left_name = QStringLiteral("Auto");
|
||||
const QString QZSettings::zwift_play_right_name = QStringLiteral("zwift_play_right_name");
|
||||
const QString QZSettings::default_zwift_play_right_name = QStringLiteral("Auto");
|
||||
|
||||
|
||||
const uint32_t allSettingsCount = 807;
|
||||
const uint32_t allSettingsCount = 810;
|
||||
|
||||
QVariant allSettings[allSettingsCount][2] = {
|
||||
{QZSettings::cryptoKeySettingsProfiles, QZSettings::default_cryptoKeySettingsProfiles},
|
||||
@@ -1564,8 +1570,6 @@ QVariant allSettings[allSettingsCount][2] = {
|
||||
{QZSettings::ftms_treadmill, QZSettings::default_ftms_treadmill},
|
||||
{QZSettings::ant_speed_offset, QZSettings::default_ant_speed_offset},
|
||||
{QZSettings::ant_speed_gain, QZSettings::default_ant_speed_gain},
|
||||
{QZSettings::ant_remote_control, QZSettings::default_ant_remote_control},
|
||||
{QZSettings::ant_remote_control_device_number, QZSettings::default_ant_remote_control_device_number},
|
||||
{QZSettings::proform_rower_sport_rl, QZSettings::default_proform_rower_sport_rl},
|
||||
{QZSettings::strava_date_prefix, QZSettings::default_strava_date_prefix},
|
||||
{QZSettings::race_mode, QZSettings::default_race_mode},
|
||||
@@ -1813,6 +1817,11 @@ QVariant allSettings[allSettingsCount][2] = {
|
||||
{QZSettings::calories_active_only, QZSettings::default_calories_active_only},
|
||||
{QZSettings::calories_from_hr, QZSettings::default_calories_from_hr},
|
||||
{QZSettings::height, QZSettings::default_height},
|
||||
{QZSettings::taurua_ic90, QZSettings::default_taurua_ic90},
|
||||
{QZSettings::proform_csx210, QZSettings::default_proform_csx210},
|
||||
{QZSettings::zwift_click_name, QZSettings::default_zwift_click_name},
|
||||
{QZSettings::zwift_play_left_name, QZSettings::default_zwift_play_left_name},
|
||||
{QZSettings::zwift_play_right_name, QZSettings::default_zwift_play_right_name},
|
||||
{QZSettings::toorxtreadmill_discovery_completed, QZSettings::default_toorxtreadmill_discovery_completed},
|
||||
};
|
||||
|
||||
|
||||
@@ -1930,12 +1930,6 @@ class QZSettings {
|
||||
static const QString ant_speed_gain;
|
||||
static constexpr float default_ant_speed_gain = 1;
|
||||
|
||||
static const QString ant_remote_control;
|
||||
static constexpr bool default_ant_remote_control = false;
|
||||
|
||||
static const QString ant_remote_control_device_number;
|
||||
static constexpr int default_ant_remote_control_device_number = 0;
|
||||
|
||||
static const QString race_mode;
|
||||
static constexpr bool default_race_mode = false;
|
||||
|
||||
@@ -2699,6 +2693,30 @@ class QZSettings {
|
||||
static const QString height;
|
||||
static constexpr double default_height = 175.0;
|
||||
|
||||
static const QString taurua_ic90;
|
||||
static constexpr bool default_taurua_ic90 = false;
|
||||
|
||||
static const QString proform_csx210;
|
||||
static constexpr bool default_proform_csx210 = false;
|
||||
|
||||
/**
|
||||
* @brief Zwift Click device MAC address selection
|
||||
*/
|
||||
static const QString zwift_click_name;
|
||||
static const QString default_zwift_click_name;
|
||||
|
||||
/**
|
||||
* @brief Zwift Play left device MAC address selection
|
||||
*/
|
||||
static const QString zwift_play_left_name;
|
||||
static const QString default_zwift_play_left_name;
|
||||
|
||||
/**
|
||||
* @brief Zwift Play right device MAC address selection
|
||||
*/
|
||||
static const QString zwift_play_right_name;
|
||||
static const QString default_zwift_play_right_name;
|
||||
|
||||
/**
|
||||
* @brief Write the QSettings values using the constants from this namespace.
|
||||
* @param showDefaults Optionally indicates if the default should be shown with the key.
|
||||
|
||||
174
src/settings.qml
174
src/settings.qml
@@ -1205,8 +1205,11 @@ import Qt.labs.platform 1.1
|
||||
property int chart_display_mode: 0
|
||||
property bool zwift_play_vibration: true
|
||||
property bool toorxtreadmill_discovery_completed: false
|
||||
property bool ant_remote_control: false
|
||||
property int ant_remote_control_device_number: 0
|
||||
property bool taurua_ic90: false
|
||||
property bool proform_csx210: false
|
||||
property string zwift_click_name: "Auto"
|
||||
property string zwift_play_left_name: "Auto"
|
||||
property string zwift_play_right_name: "Auto"
|
||||
}
|
||||
|
||||
|
||||
@@ -4012,7 +4015,8 @@ import Qt.labs.platform 1.1
|
||||
"Nordictrack GX 4.4 Pro",
|
||||
"TDF 1.0 PFEVEX71316.0",
|
||||
"Proform XBike",
|
||||
"Proform 225 CSX PFEX32925 INT.0"
|
||||
"Proform 225 CSX PFEX32925 INT.0",
|
||||
"Proform CSX210"
|
||||
]
|
||||
|
||||
// Initialize when the accordion content becomes visible
|
||||
@@ -4047,7 +4051,8 @@ import Qt.labs.platform 1.1
|
||||
settings.nordictrack_gx_44_pro ? 15 :
|
||||
settings.proform_bike_PFEVEX71316_0 ? 16 :
|
||||
settings.proform_xbike ? 17 :
|
||||
settings.proform_225_csx_PFEX32925_INT_0 ? 18 : 0;
|
||||
settings.proform_225_csx_PFEX32925_INT_0 ? 18 :
|
||||
settings.proform_csx210 ? 19 : 0;
|
||||
|
||||
console.log("bikeModelComboBox selected model: " + selectedModel);
|
||||
if (selectedModel >= 0) {
|
||||
@@ -4080,6 +4085,7 @@ import Qt.labs.platform 1.1
|
||||
settings.proform_bike_PFEVEX71316_0 = false;
|
||||
settings.proform_xbike = false;
|
||||
settings.proform_225_csx_PFEX32925_INT_0 = false;
|
||||
settings.proform_csx210 = false;
|
||||
|
||||
// Set corresponding setting for selected model
|
||||
switch (currentIndex) {
|
||||
@@ -4101,6 +4107,7 @@ import Qt.labs.platform 1.1
|
||||
case 16: settings.proform_bike_PFEVEX71316_0 = true; break;
|
||||
case 17: settings.proform_xbike = true; break;
|
||||
case 18: settings.proform_225_csx_PFEX32925_INT_0 = true; break;
|
||||
case 19: settings.proform_csx210 = true; break;
|
||||
}
|
||||
|
||||
window.settings_restart_to_apply = true;
|
||||
@@ -4634,69 +4641,6 @@ import Qt.labs.platform 1.1
|
||||
Layout.fillWidth: true
|
||||
color: Material.color(Material.Lime)
|
||||
}
|
||||
|
||||
IndicatorOnlySwitch {
|
||||
text: qsTr("ANT+ Remote Control")
|
||||
spacing: 0
|
||||
bottomPadding: 0
|
||||
topPadding: 0
|
||||
rightPadding: 0
|
||||
leftPadding: 0
|
||||
clip: false
|
||||
checked: settings.ant_remote_control
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
onClicked: { settings.ant_remote_control = checked; window.settings_restart_to_apply = true; }
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Enable ANT+ Remote Control support (like Zwift Click). Menu Up/Down buttons control gear shifting. Works with standard ANT+ Control Device remotes. Default: Disabled")
|
||||
font.bold: true
|
||||
font.italic: true
|
||||
font.pixelSize: Qt.application.font.pixelSize - 2
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.WordWrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
color: Material.color(Material.Lime)
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
Label {
|
||||
text: qsTr("ANT+ Remote Control Device Number (0 = any):")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
TextField {
|
||||
id: antRemoteControlDeviceNumberTextField
|
||||
text: settings.ant_remote_control_device_number
|
||||
horizontalAlignment: Text.AlignRight
|
||||
Layout.fillHeight: false
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
inputMethodHints: Qt.ImhDigitsOnly
|
||||
onAccepted: settings.ant_remote_control_device_number = text
|
||||
onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length
|
||||
}
|
||||
Button {
|
||||
text: "OK"
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
onClicked: { settings.ant_remote_control_device_number = antRemoteControlDeviceNumberTextField.text; window.settings_restart_to_apply = true; toast.show("Setting saved!"); }
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Set device number to 0 to accept any ANT+ remote control, or specify a specific device number to pair with only that remote.")
|
||||
font.bold: true
|
||||
font.italic: true
|
||||
font.pixelSize: Qt.application.font.pixelSize - 2
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.WordWrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
color: Material.color(Material.Lime)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
@@ -8731,7 +8675,21 @@ import Qt.labs.platform 1.1
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
onClicked: { settings.hop_sport_hs_090h_bike = checked; window.settings_restart_to_apply = true; }
|
||||
}
|
||||
}
|
||||
|
||||
IndicatorOnlySwitch {
|
||||
text: qsTr("Taurua IC90 Bike")
|
||||
spacing: 0
|
||||
bottomPadding: 0
|
||||
topPadding: 0
|
||||
rightPadding: 0
|
||||
leftPadding: 0
|
||||
clip: false
|
||||
checked: settings.taurua_ic90
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
onClicked: { settings.taurua_ic90 = checked; window.settings_restart_to_apply = true; }
|
||||
}
|
||||
|
||||
IndicatorOnlySwitch {
|
||||
id: jtxFitnessSprintTreadmillDelegate
|
||||
@@ -11707,7 +11665,85 @@ import Qt.labs.platform 1.1
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
color: Material.color(Material.Lime)
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Zwift Click Device")
|
||||
visible: settings.zwift_click
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: zwiftClickDeviceCombo
|
||||
visible: settings.zwift_click
|
||||
Layout.fillWidth: true
|
||||
model: rootItem.bluetooth ? rootItem.bluetooth.zwiftClickDevices : ["Auto"]
|
||||
currentIndex: {
|
||||
if (rootItem.bluetooth && rootItem.bluetooth.zwiftClickDevices) {
|
||||
return Math.max(0, rootItem.bluetooth.zwiftClickDevices.indexOf(settings.zwift_click_name))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
onCurrentTextChanged: {
|
||||
if (currentText && currentText !== settings.zwift_click_name) {
|
||||
settings.zwift_click_name = currentText
|
||||
window.settings_restart_to_apply = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Zwift Play Left Device")
|
||||
visible: settings.zwift_play
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: zwiftPlayLeftDeviceCombo
|
||||
visible: settings.zwift_play
|
||||
Layout.fillWidth: true
|
||||
model: rootItem.bluetooth ? rootItem.bluetooth.zwiftPlayDevices : ["Auto"]
|
||||
currentIndex: {
|
||||
if (rootItem.bluetooth && rootItem.bluetooth.zwiftPlayDevices) {
|
||||
return Math.max(0, rootItem.bluetooth.zwiftPlayDevices.indexOf(settings.zwift_play_left_name))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
onCurrentTextChanged: {
|
||||
if (currentText && currentText !== settings.zwift_play_left_name) {
|
||||
settings.zwift_play_left_name = currentText
|
||||
window.settings_restart_to_apply = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Zwift Play Right Device")
|
||||
visible: settings.zwift_play
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: zwiftPlayRightDeviceCombo
|
||||
visible: settings.zwift_play
|
||||
Layout.fillWidth: true
|
||||
model: rootItem.bluetooth ? rootItem.bluetooth.zwiftPlayDevices : ["Auto"]
|
||||
currentIndex: {
|
||||
if (rootItem.bluetooth && rootItem.bluetooth.zwiftPlayDevices) {
|
||||
return Math.max(0, rootItem.bluetooth.zwiftPlayDevices.indexOf(settings.zwift_play_right_name))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
onCurrentTextChanged: {
|
||||
if (currentText && currentText !== settings.zwift_play_right_name) {
|
||||
settings.zwift_play_right_name = currentText
|
||||
window.settings_restart_to_apply = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IndicatorOnlySwitch {
|
||||
text: qsTr("Buttons debouncing")
|
||||
|
||||
Reference in New Issue
Block a user