mirror of
https://github.com/cagnulein/qdomyos-zwift.git
synced 2026-02-18 00:17:41 +01:00
Compare commits
15 Commits
Computrain
...
build-1214
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d33d87f04 | ||
|
|
b15055e914 | ||
|
|
5ddb5f08cd | ||
|
|
13161cd894 | ||
|
|
3089dc8a1c | ||
|
|
f38652f7b2 | ||
|
|
fdbc6e94e1 | ||
|
|
025815fe99 | ||
|
|
e2a93cde72 | ||
|
|
a44002c924 | ||
|
|
3bcd4d0ee4 | ||
|
|
e15e8ebf9e | ||
|
|
fba48cb7da | ||
|
|
daacf806bf | ||
|
|
4c21b01903 |
@@ -4569,7 +4569,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1212;
|
||||
CURRENT_PROJECT_VERSION = 1214;
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -4770,7 +4770,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1212;
|
||||
CURRENT_PROJECT_VERSION = 1214;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = YES;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
@@ -5007,7 +5007,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1212;
|
||||
CURRENT_PROJECT_VERSION = 1214;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -5103,7 +5103,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1212;
|
||||
CURRENT_PROJECT_VERSION = 1214;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = 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 = 1212;
|
||||
CURRENT_PROJECT_VERSION = 1214;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -5311,7 +5311,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1212;
|
||||
CURRENT_PROJECT_VERSION = 1214;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
|
||||
ENABLE_BITCODE = YES;
|
||||
@@ -5421,7 +5421,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = QZWidgetExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1212;
|
||||
CURRENT_PROJECT_VERSION = 1214;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -5512,7 +5512,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = QZWidgetExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1212;
|
||||
CURRENT_PROJECT_VERSION = 1214;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
|
||||
@@ -1677,6 +1677,7 @@ void ftmsbike::deviceDiscovered(const QBluetoothDeviceInfo &device) {
|
||||
} else if(bluetoothDevice.name().toUpper().startsWith("JFBK5.0") || bluetoothDevice.name().toUpper().startsWith("JFBK7.0")) {
|
||||
qDebug() << QStringLiteral("JFBK5.0 found");
|
||||
resistance_lvl_mode = true;
|
||||
ergModeSupported = false;
|
||||
JFBK5_0 = true;
|
||||
} else if((bluetoothDevice.name().toUpper().startsWith("BIKE-"))) {
|
||||
qDebug() << QStringLiteral("BIKE- found");
|
||||
|
||||
@@ -2574,6 +2574,7 @@ void horizontreadmill::deviceDiscovered(const QBluetoothDeviceInfo &device) {
|
||||
qDebug() << QStringLiteral("HORIZON_7.8AT workaround ON!");
|
||||
} else if(device.name().toUpper().startsWith("T01_")) {
|
||||
QSettings settings;
|
||||
T01 = true;
|
||||
iconcept_ftms_treadmill_inclination_table = settings.value(QZSettings::iconcept_ftms_treadmill_inclination_table, QZSettings::default_iconcept_ftms_treadmill_inclination_table).toBool();
|
||||
if(iconcept_ftms_treadmill_inclination_table) {
|
||||
ICONCEPT_FTMS_treadmill = true;
|
||||
@@ -3333,7 +3334,7 @@ void horizontreadmill::testProfileCRC() {
|
||||
double horizontreadmill::minStepInclination() {
|
||||
QSettings settings;
|
||||
bool toorx_ftms_treadmill = settings.value(QZSettings::toorx_ftms_treadmill, QZSettings::default_toorx_ftms_treadmill).toBool();
|
||||
if (kettler_treadmill || trx3500_treadmill || toorx_ftms_treadmill || sole_tt8_treadmill || ICONCEPT_FTMS_treadmill || SW_TREADMILL || sole_s77_treadmill || FIT || T3G_PRO || T3G_ELITE)
|
||||
if (kettler_treadmill || T01 || trx3500_treadmill || toorx_ftms_treadmill || sole_tt8_treadmill || ICONCEPT_FTMS_treadmill || SW_TREADMILL || sole_s77_treadmill || FIT || T3G_PRO || T3G_ELITE)
|
||||
return 1.0;
|
||||
else
|
||||
return 0.5;
|
||||
|
||||
@@ -113,6 +113,7 @@ class horizontreadmill : public treadmill {
|
||||
bool T3G_PRO = false;
|
||||
bool T3G_ELITE = false;
|
||||
bool TP1 = false;
|
||||
bool T01 = false;
|
||||
|
||||
void testProfileCRC();
|
||||
void updateProfileCRC();
|
||||
|
||||
@@ -23,13 +23,14 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* CONSTRUCTOR/DESTRUCTOR
|
||||
* ---------------------------------------------------------------------- */
|
||||
KettlerUSB::KettlerUSB(QObject *parent, QString devname) : QThread(parent) {
|
||||
KettlerUSB::KettlerUSB(QObject *parent, QString devname, int baudrate) : QThread(parent) {
|
||||
devicePower = deviceHeartRate = deviceCadence = deviceSpeed = deviceDistance = 0.00;
|
||||
targetPower = DEFAULT_POWER;
|
||||
writePower = false;
|
||||
setDevice(devname);
|
||||
deviceStatus = 0;
|
||||
this->parent = parent;
|
||||
this->baudrate = baudrate;
|
||||
}
|
||||
|
||||
KettlerUSB::~KettlerUSB() {}
|
||||
@@ -85,21 +86,46 @@ void KettlerUSB::parseStatusResponse(const QString &response) {
|
||||
// HR RPM Speed Distance Power Energy Time CurrentPower
|
||||
// Example: 101\t047\t074\t002\t025\t0312\t01:12\t025
|
||||
|
||||
// Ignore non-status responses (ACK, ERROR, etc.)
|
||||
if (response == "ACK" || response == "ERROR" || response.length() < 10) {
|
||||
qDebug() << " Skipping non-status response:" << response;
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList fields = response.split('\t');
|
||||
if (fields.size() >= 8) {
|
||||
pvars.lock();
|
||||
deviceHeartRate = fields[0].toDouble();
|
||||
deviceCadence = fields[1].toDouble();
|
||||
deviceSpeed = fields[2].toDouble() * 0.1; // Speed is in 0.1 km/h
|
||||
deviceDistance = fields[3].toDouble() * 100; // Distance is in 100m units
|
||||
devicePower = fields[7].toDouble(); // CurrentPower (last field)
|
||||
pvars.unlock();
|
||||
// Additional validation: check if fields contain numeric data
|
||||
bool validData = true;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (i != 6) { // Skip time field (format HH:MM)
|
||||
bool ok;
|
||||
fields[i].toDouble(&ok);
|
||||
if (!ok && i != 3 && i != 5) { // Distance and Energy can be non-numeric sometimes
|
||||
validData = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Kettler Status: HR=" << deviceHeartRate
|
||||
<< " RPM=" << deviceCadence
|
||||
<< " Speed=" << deviceSpeed
|
||||
<< " Dist=" << deviceDistance
|
||||
<< " Power=" << devicePower;
|
||||
if (validData) {
|
||||
pvars.lock();
|
||||
deviceHeartRate = fields[0].toDouble();
|
||||
deviceCadence = fields[1].toDouble();
|
||||
deviceSpeed = fields[2].toDouble() * 0.1; // Speed is in 0.1 km/h
|
||||
deviceDistance = fields[3].toDouble() * 100; // Distance is in 100m units
|
||||
devicePower = fields[7].toDouble(); // CurrentPower (last field)
|
||||
pvars.unlock();
|
||||
|
||||
qDebug() << "Kettler Status: HR=" << deviceHeartRate
|
||||
<< " RPM=" << deviceCadence
|
||||
<< " Speed=" << deviceSpeed
|
||||
<< " Dist=" << deviceDistance
|
||||
<< " Power=" << devicePower;
|
||||
} else {
|
||||
qDebug() << " Invalid status data (non-numeric fields):" << response;
|
||||
}
|
||||
} else {
|
||||
qDebug() << " Invalid status format (expected 8 fields, got" << fields.size() << "):" << response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,6 +214,10 @@ void KettlerUSB::run() {
|
||||
// Send initialization sequence
|
||||
initSequence();
|
||||
|
||||
// Flush buffer after init to clear any leftover responses
|
||||
KettlerSleeper::msleep(500);
|
||||
flushSerialBuffer();
|
||||
|
||||
// Wait 3 seconds before first poll (as per kettlerUSB2BLE)
|
||||
KettlerSleeper::msleep(3000);
|
||||
|
||||
@@ -200,13 +230,27 @@ void KettlerUSB::run() {
|
||||
pvars.unlock();
|
||||
|
||||
if (curWritePower) {
|
||||
// Send power command instead of status request
|
||||
// Send power command
|
||||
QString powerCmd = QString("PW%1").arg((int)curPower);
|
||||
sendCommand(powerCmd);
|
||||
|
||||
pvars.lock();
|
||||
this->writePower = false;
|
||||
pvars.unlock();
|
||||
|
||||
// Read and discard response (usually ACK or a number)
|
||||
KettlerSleeper::msleep(150);
|
||||
QString pwResponse = readResponse();
|
||||
if (!pwResponse.isEmpty()) {
|
||||
qDebug() << " PW response (discarded):" << pwResponse;
|
||||
}
|
||||
|
||||
// Immediately send ST to get fresh status
|
||||
sendCommand("ST");
|
||||
QString response = readResponse();
|
||||
if (!response.isEmpty()) {
|
||||
parseStatusResponse(response);
|
||||
}
|
||||
} else {
|
||||
// Normal status poll
|
||||
sendCommand("ST");
|
||||
@@ -216,8 +260,8 @@ void KettlerUSB::run() {
|
||||
}
|
||||
}
|
||||
|
||||
// Wait 2 seconds between polls (as per kettlerUSB2BLE)
|
||||
KettlerSleeper::msleep(2000);
|
||||
// Reduced polling interval from 2000ms to 500ms for faster response
|
||||
KettlerSleeper::msleep(500);
|
||||
}
|
||||
|
||||
// Check status
|
||||
@@ -276,11 +320,11 @@ int KettlerUSB::closePort() {
|
||||
|
||||
int KettlerUSB::openPort() {
|
||||
#ifdef Q_OS_ANDROID
|
||||
// Call Java Usbserial with 9600 baud for Kettler
|
||||
// Call Java Usbserial with configured baud rate for Kettler
|
||||
QAndroidJniObject::callStaticMethod<void>("org/cagnulen/qdomyoszwift/Usbserial", "open",
|
||||
"(Landroid/content/Context;I)V",
|
||||
QtAndroid::androidContext().object(),
|
||||
9600);
|
||||
baudrate);
|
||||
#elif !defined(WIN32)
|
||||
// LINUX AND MAC USES TERMIO / IOCTL / STDIO
|
||||
|
||||
@@ -301,7 +345,14 @@ int KettlerUSB::openPort() {
|
||||
tcgetattr(devicePort, &deviceSettings);
|
||||
|
||||
cfmakeraw(&deviceSettings);
|
||||
cfsetspeed(&deviceSettings, B9600); // Kettler uses 9600 baud
|
||||
// Convert int baudrate to speed_t constant
|
||||
speed_t speed;
|
||||
switch (baudrate) {
|
||||
case 57600: speed = B57600; break;
|
||||
case 9600:
|
||||
default: speed = B9600; break;
|
||||
}
|
||||
cfsetspeed(&deviceSettings, speed);
|
||||
|
||||
deviceSettings.c_iflag &=
|
||||
~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ICANON | ISTRIP | IXON | IXOFF | IXANY);
|
||||
@@ -347,7 +398,12 @@ int KettlerUSB::openPort() {
|
||||
if (GetCommState(devicePort, &deviceSettings) == false)
|
||||
return -1;
|
||||
|
||||
deviceSettings.BaudRate = CBR_9600; // Kettler uses 9600 baud
|
||||
// Convert int baudrate to Windows CBR constant
|
||||
switch (baudrate) {
|
||||
case 57600: deviceSettings.BaudRate = CBR_57600; break;
|
||||
case 9600:
|
||||
default: deviceSettings.BaudRate = CBR_9600; break;
|
||||
}
|
||||
deviceSettings.fParity = NOPARITY;
|
||||
deviceSettings.ByteSize = 8;
|
||||
deviceSettings.StopBits = ONESTOPBIT;
|
||||
@@ -453,6 +509,20 @@ QString KettlerUSB::rawRead() {
|
||||
return result;
|
||||
}
|
||||
|
||||
void KettlerUSB::flushSerialBuffer() {
|
||||
qDebug() << "Flushing serial buffer...";
|
||||
#ifdef Q_OS_ANDROID
|
||||
// Clear Android buffer
|
||||
rxBuffer.clear();
|
||||
// Read and discard any pending data
|
||||
QAndroidJniObject::callStaticObjectMethod("org/cagnulen/qdomyoszwift/Usbserial", "read", "()[B");
|
||||
#elif defined(WIN32)
|
||||
PurgeComm(devicePort, PURGE_RXCLEAR | PURGE_TXCLEAR);
|
||||
#else
|
||||
tcflush(devicePort, TCIOFLUSH);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool KettlerUSB::discover(QString filename) {
|
||||
if (filename.isEmpty())
|
||||
return false;
|
||||
|
||||
@@ -64,10 +64,11 @@
|
||||
class KettlerUSB : public QThread {
|
||||
|
||||
public:
|
||||
KettlerUSB(QObject *parent = 0, QString deviceFilename = 0);
|
||||
KettlerUSB(QObject *parent = 0, QString deviceFilename = 0, int baudrate = 9600);
|
||||
~KettlerUSB();
|
||||
|
||||
QObject *parent;
|
||||
int baudrate = 9600;
|
||||
|
||||
// HIGH-LEVEL FUNCTIONS
|
||||
int start(); // Calls QThread to start
|
||||
@@ -126,6 +127,7 @@ class KettlerUSB : public QThread {
|
||||
// raw device utils
|
||||
int rawWrite(const char *bytes, int size);
|
||||
QString rawRead();
|
||||
void flushSerialBuffer(); // Flush any pending data in serial buffer
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
QByteArray rxBuffer;
|
||||
|
||||
@@ -48,8 +48,10 @@ kettlerusbbike::kettlerusbbike(bool noWriteResistance, bool noHeartService, int8
|
||||
|
||||
QString kettlerSerialPort =
|
||||
settings.value(QZSettings::kettler_usb_serialport, QZSettings::default_kettler_usb_serialport).toString();
|
||||
int kettlerBaudrate =
|
||||
settings.value(QZSettings::kettler_usb_baudrate, QZSettings::default_kettler_usb_baudrate).toInt();
|
||||
|
||||
myKettler = new KettlerUSB(this, kettlerSerialPort);
|
||||
myKettler = new KettlerUSB(this, kettlerSerialPort, kettlerBaudrate);
|
||||
myKettler->start();
|
||||
|
||||
ergModeSupported = true; // ERG mode supported
|
||||
|
||||
@@ -26,6 +26,10 @@ nordictrackelliptical::nordictrackelliptical(bool noWriteResistance, bool noHear
|
||||
this->noHeartService = noHeartService;
|
||||
this->bikeResistanceGain = bikeResistanceGain;
|
||||
this->bikeResistanceOffset = bikeResistanceOffset;
|
||||
|
||||
QSettings settings;
|
||||
nordictrack_se7i = settings.value(QZSettings::nordictrack_se7i, QZSettings::default_nordictrack_se7i).toBool();
|
||||
|
||||
initDone = false;
|
||||
connect(refresh, &QTimer::timeout, this, &nordictrackelliptical::update);
|
||||
refresh->start(200ms);
|
||||
@@ -277,6 +281,13 @@ void nordictrackelliptical::forceIncline(double requestIncline) {
|
||||
writeCharacteristic((uint8_t *)inc200, sizeof(inc200), QStringLiteral("inc200"), false, true);
|
||||
break;
|
||||
}
|
||||
} else if (nordictrack_se7i) {
|
||||
// SE7i uses ff 0d packet with byte[10]=0x02 for incline
|
||||
// Incline encoding: value = incline% * 100
|
||||
uint16_t incValue = (uint16_t)(requestIncline * 100);
|
||||
uint8_t incCmd[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x06, 0x09, 0x02, 0x01,
|
||||
0x02, (uint8_t)(incValue & 0xFF), (uint8_t)((incValue >> 8) & 0xFF), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
writeCharacteristic(incCmd, sizeof(incCmd), QStringLiteral("incline_se7i"), false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,6 +416,13 @@ void nordictrackelliptical::forceResistance(resistance_t requestResistance) {
|
||||
writeCharacteristic((uint8_t *)res22, sizeof(res22), QStringLiteral("resistance22"), false, true);
|
||||
break;
|
||||
}
|
||||
} else if (nordictrack_se7i) {
|
||||
// SE7i uses ff 0d packet with byte[10]=0x04 for resistance
|
||||
// Resistance encoding: value = resistance * 454 - 1
|
||||
uint16_t resValue = (requestResistance * 454) - 1;
|
||||
uint8_t resCmd[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x06, 0x09, 0x02, 0x01,
|
||||
0x04, (uint8_t)(resValue & 0xFF), (uint8_t)((resValue >> 8) & 0xFF), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
writeCharacteristic(resCmd, sizeof(resCmd), QStringLiteral("resistance_se7i"), false, true);
|
||||
} else if (proform_hybrid_trainer_xt) {
|
||||
const uint8_t res1[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x06, 0x09, 0x02, 0x01,
|
||||
0x04, 0x32, 0x02, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
@@ -669,6 +687,63 @@ void nordictrackelliptical::update() {
|
||||
if (counterPoll > 4) {
|
||||
counterPoll = 0;
|
||||
}
|
||||
} else if (nordictrack_se7i) {
|
||||
// NordicTrack Elliptical SE7i - 6 packet sendPoll cycle
|
||||
uint8_t se7i_noOpData1[] = {0xfe, 0x02, 0x17, 0x03};
|
||||
uint8_t se7i_noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x06, 0x13, 0x02, 0x00,
|
||||
0x0d, 0x3e, 0x96, 0x33, 0x00, 0x10, 0x40, 0x50, 0x00, 0x80};
|
||||
uint8_t se7i_noOpData3[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x05, 0x54, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t se7i_noOpData4[] = {0xfe, 0x02, 0x17, 0x03};
|
||||
uint8_t se7i_noOpData5[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x06, 0x13, 0x02, 0x00,
|
||||
0x0d, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t se7i_noOpData6[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x90, 0x78, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
switch (counterPoll) {
|
||||
case 0:
|
||||
writeCharacteristic(se7i_noOpData1, sizeof(se7i_noOpData1), QStringLiteral("noOp"));
|
||||
break;
|
||||
case 1:
|
||||
writeCharacteristic(se7i_noOpData2, sizeof(se7i_noOpData2), QStringLiteral("noOp"));
|
||||
break;
|
||||
case 2:
|
||||
writeCharacteristic(se7i_noOpData3, sizeof(se7i_noOpData3), QStringLiteral("noOp"));
|
||||
if (requestResistance != -1) {
|
||||
if (requestResistance < 0)
|
||||
requestResistance = 0;
|
||||
if (requestResistance != currentResistance().value() && requestResistance >= 0 &&
|
||||
requestResistance <= max_resistance) {
|
||||
emit debug(QStringLiteral("writing resistance ") + QString::number(requestResistance));
|
||||
forceResistance(requestResistance);
|
||||
}
|
||||
requestResistance = -1;
|
||||
}
|
||||
if (requestInclination != -1) {
|
||||
if (requestInclination < 0)
|
||||
requestInclination = 0;
|
||||
if (requestInclination != currentInclination().value() && requestInclination >= 0 &&
|
||||
requestInclination <= max_inclination) {
|
||||
emit debug(QStringLiteral("writing inclination ") + QString::number(requestInclination));
|
||||
forceIncline(requestInclination);
|
||||
}
|
||||
requestInclination = -1;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
writeCharacteristic(se7i_noOpData4, sizeof(se7i_noOpData4), QStringLiteral("noOp"));
|
||||
break;
|
||||
case 4:
|
||||
writeCharacteristic(se7i_noOpData5, sizeof(se7i_noOpData5), QStringLiteral("noOp"));
|
||||
break;
|
||||
case 5:
|
||||
writeCharacteristic(se7i_noOpData6, sizeof(se7i_noOpData6), QStringLiteral("noOp"));
|
||||
break;
|
||||
}
|
||||
counterPoll++;
|
||||
if (counterPoll > 5) {
|
||||
counterPoll = 0;
|
||||
}
|
||||
} else {
|
||||
uint8_t noOpData1[] = {0xfe, 0x02, 0x17, 0x03};
|
||||
uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x06, 0x13, 0x02, 0x00,
|
||||
@@ -958,6 +1033,28 @@ void nordictrackelliptical::characteristicChanged(const QLowEnergyCharacteristic
|
||||
|
||||
lastPacket = newValue;
|
||||
|
||||
// SE7i Speed and Cadence parsing (Type 0x01 packets with byte[4]=0x46)
|
||||
if (nordictrack_se7i && newValue.length() == 20 && newValue.at(0) == 0x01 && newValue.at(1) == 0x12 &&
|
||||
newValue.at(4) == 0x46 && initDone == true) {
|
||||
// Parse speed from bytes 12-13 (little endian, divided by 100)
|
||||
Speed = (double)(((uint16_t)((uint8_t)newValue.at(13)) << 8) + (uint16_t)((uint8_t)newValue.at(12))) / 100.0;
|
||||
emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value()));
|
||||
lastSpeedChanged = QDateTime::currentDateTime();
|
||||
|
||||
// Parse cadence from byte 2
|
||||
uint8_t c = newValue.at(2);
|
||||
if (c > 0)
|
||||
Cadence = (c * cadence_gain) + cadence_offset;
|
||||
else
|
||||
Cadence = 0;
|
||||
emit debug(QStringLiteral("Current Cadence: ") + QString::number(Cadence.value()));
|
||||
if (Cadence.value() > 0) {
|
||||
CrankRevs++;
|
||||
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!proform_hybrid_trainer_xt && !nordictrack_elliptical_c7_5 && newValue.length() == 20 &&
|
||||
newValue.at(0) == 0x01 && newValue.at(1) == 0x12 && newValue.at(19) == 0x2C) {
|
||||
uint8_t c = newValue.at(2);
|
||||
@@ -973,7 +1070,7 @@ void nordictrackelliptical::characteristicChanged(const QLowEnergyCharacteristic
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nordictrack_elliptical_c7_5 && newValue.length() == 20 && newValue.at(0) == 0x01 && newValue.at(1) == 0x12 &&
|
||||
if (!nordictrack_elliptical_c7_5 && !nordictrack_se7i && newValue.length() == 20 && newValue.at(0) == 0x01 && newValue.at(1) == 0x12 &&
|
||||
initDone == true) {
|
||||
Speed = (double)(((uint16_t)((uint8_t)newValue.at(15)) << 8) + (uint16_t)((uint8_t)newValue.at(14))) / 100.0;
|
||||
emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value()));
|
||||
@@ -985,7 +1082,7 @@ void nordictrackelliptical::characteristicChanged(const QLowEnergyCharacteristic
|
||||
emit debug(QStringLiteral("Current Heart from machinery: ") + QString::number(heart));
|
||||
}
|
||||
|
||||
} else if (QDateTime::currentDateTime().secsTo(lastSpeedChanged) > 3) {
|
||||
} else if (!nordictrack_se7i && QDateTime::currentDateTime().secsTo(lastSpeedChanged) > 3) {
|
||||
Speed = 0;
|
||||
emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value()));
|
||||
}
|
||||
@@ -1021,13 +1118,15 @@ void nordictrackelliptical::characteristicChanged(const QLowEnergyCharacteristic
|
||||
emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value()));
|
||||
}
|
||||
|
||||
if (newValue.length() != 20 || (newValue.at(0) != 0x00 && newValue.at(0) != 0x01) || newValue.at(1) != 0x12 ||
|
||||
// Skip the strict packet validation for SE7i (it has different packet structures)
|
||||
if (!nordictrack_se7i &&
|
||||
(newValue.length() != 20 || (newValue.at(0) != 0x00 && newValue.at(0) != 0x01) || newValue.at(1) != 0x12 ||
|
||||
newValue.at(2) != 0x01 || newValue.at(3) != 0x04 || newValue.at(4) != 0x02 ||
|
||||
(newValue.at(5) != 0x2e && newValue.at(5) != 0x30 && newValue.at(5) != 0x31) ||
|
||||
(((uint8_t)newValue.at(12)) == 0xFF && ((uint8_t)newValue.at(13)) == 0xFF &&
|
||||
((uint8_t)newValue.at(14)) == 0xFF && ((uint8_t)newValue.at(15)) == 0xFF &&
|
||||
((uint8_t)newValue.at(16)) == 0xFF && ((uint8_t)newValue.at(17)) == 0xFF &&
|
||||
((uint8_t)newValue.at(18)) == 0xFF && ((uint8_t)newValue.at(19)) == 0xFF)) {
|
||||
((uint8_t)newValue.at(18)) == 0xFF && ((uint8_t)newValue.at(19)) == 0xFF))) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1046,7 +1145,20 @@ void nordictrackelliptical::characteristicChanged(const QLowEnergyCharacteristic
|
||||
}
|
||||
}
|
||||
|
||||
if (!nordictrack_elliptical_c7_5) {
|
||||
if (nordictrack_se7i && newValue.length() == 20 && newValue.at(0) == 0x00 &&
|
||||
newValue.at(1) == 0x12 && newValue.at(2) == 0x01 && newValue.at(3) == 0x04 && newValue.at(4) == 0x02 &&
|
||||
(newValue.at(5) == 0x30 || newValue.at(5) == 0x31)) {
|
||||
// SE7i Resistance and Inclination parsing (Type 0x00 packets)
|
||||
// Inclination from bytes 10-11 (little endian, divided by 100)
|
||||
uint16_t incValue = ((uint16_t)((uint8_t)newValue.at(10))) + ((uint16_t)((uint8_t)newValue.at(11)) << 8);
|
||||
Inclination = ((double)incValue) / 100.0;
|
||||
emit debug(QStringLiteral("Current Inclination from packet: ") + QString::number(Inclination.value()));
|
||||
|
||||
// Resistance from bytes 12-13 (little endian): resistance = (value + 1) / 454
|
||||
uint16_t resValue = ((uint16_t)((uint8_t)newValue.at(12))) + ((uint16_t)((uint8_t)newValue.at(13)) << 8);
|
||||
Resistance = ((double)(resValue + 1)) / 454.0;
|
||||
emit debug(QStringLiteral("Current Resistance from packet: ") + QString::number(Resistance.value()));
|
||||
} else if (!nordictrack_elliptical_c7_5 && !nordictrack_se7i) {
|
||||
Resistance = GetResistanceFromPacket(newValue);
|
||||
} else if (nordictrack_elliptical_c7_5 && newValue.length() == 20 && newValue.at(0) == 0x00 &&
|
||||
newValue.at(1) == 0x12 && newValue.at(2) == 0x01 && newValue.at(3) == 0x04 && newValue.at(4) == 0x02 &&
|
||||
@@ -1203,7 +1315,68 @@ void nordictrackelliptical::btinit() {
|
||||
QThread::msleep(400);
|
||||
writeCharacteristic(initData9, sizeof(initData9), QStringLiteral("init"), false, false);
|
||||
QThread::msleep(400);
|
||||
if (nordictrack_elliptical_c7_5) {
|
||||
if (nordictrack_se7i) {
|
||||
// NordicTrack Elliptical SE7i initialization (19 packets: pkt944 to pkt1020)
|
||||
max_resistance = 22;
|
||||
max_inclination = 20;
|
||||
|
||||
uint8_t se7i_initData1[] = {0xfe, 0x02, 0x08, 0x02};
|
||||
uint8_t se7i_initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t se7i_initData3[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x80, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t se7i_initData4[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x88, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t se7i_initData5[] = {0xfe, 0x02, 0x0b, 0x02}; // pkt972
|
||||
uint8_t se7i_initData6[] = {0xff, 0x0b, 0x02, 0x04, 0x02, 0x07, 0x02, 0x07, 0x82, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // pkt975
|
||||
uint8_t se7i_initData7[] = {0xfe, 0x02, 0x0a, 0x02}; // pkt982
|
||||
uint8_t se7i_initData8[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x84, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // pkt985
|
||||
uint8_t se7i_initData9[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x95, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // pkt994
|
||||
uint8_t se7i_initData10[] = {0xfe, 0x02, 0x2c, 0x04}; // pkt1000
|
||||
uint8_t se7i_initData11[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x06, 0x28, 0x90, 0x04, 0x00, 0x0d, 0x68, 0xc9, 0x28, 0x95, 0xf0, 0x69, 0xc0, 0x3d}; // pkt1003
|
||||
uint8_t se7i_initData12[] = {0x01, 0x12, 0xa8, 0x19, 0x88, 0xf5, 0x60, 0xf9, 0x70, 0xcd, 0x48, 0xc9, 0x48, 0xf5, 0x70, 0xe9, 0x60, 0x1d, 0x88, 0x39}; // pkt1006
|
||||
uint8_t se7i_initData13[] = {0xff, 0x08, 0xa8, 0x55, 0xc0, 0x80, 0x02, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // pkt1009
|
||||
uint8_t se7i_initData14[] = {0xfe, 0x02, 0x19, 0x03}; // pkt1014
|
||||
uint8_t se7i_initData15[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x06, 0x15, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // pkt1017
|
||||
uint8_t se7i_initData16[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // pkt1020
|
||||
|
||||
int sleepms = 400;
|
||||
writeCharacteristic(se7i_initData1, sizeof(se7i_initData1), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData2, sizeof(se7i_initData2), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData1, sizeof(se7i_initData1), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData3, sizeof(se7i_initData3), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData1, sizeof(se7i_initData1), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData4, sizeof(se7i_initData4), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData5, sizeof(se7i_initData5), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData6, sizeof(se7i_initData6), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData7, sizeof(se7i_initData7), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData8, sizeof(se7i_initData8), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData1, sizeof(se7i_initData1), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData9, sizeof(se7i_initData9), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData10, sizeof(se7i_initData10), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData11, sizeof(se7i_initData11), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData12, sizeof(se7i_initData12), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData13, sizeof(se7i_initData13), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData14, sizeof(se7i_initData14), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData15, sizeof(se7i_initData15), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
writeCharacteristic(se7i_initData16, sizeof(se7i_initData16), QStringLiteral("init"), false, true);
|
||||
QThread::msleep(sleepms);
|
||||
} else if (nordictrack_elliptical_c7_5) {
|
||||
max_resistance = 22;
|
||||
max_inclination = 20;
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ class nordictrackelliptical : public elliptical {
|
||||
|
||||
bool noWriteResistance = false;
|
||||
bool noHeartService = false;
|
||||
bool nordictrack_se7i = false;
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
lockscreen *h = 0;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <QThread>
|
||||
#include <math.h>
|
||||
#include <limits>
|
||||
#ifdef Q_OS_ANDROID
|
||||
#include "keepawakehelper.h"
|
||||
#include <QLowEnergyConnectionParameters>
|
||||
@@ -349,6 +350,7 @@ void schwinnic4bike::characteristicChanged(const QLowEnergyCharacteristic &chara
|
||||
emit resistanceRead(Resistance.value());
|
||||
} else {
|
||||
Resistance = ResistanceFromFTMSAccessory.value();
|
||||
m_pelotonResistance = bikeResistanceToPeloton(ResistanceFromFTMSAccessory.value());
|
||||
}
|
||||
|
||||
lastRefreshCharacteristicChanged = now;
|
||||
@@ -628,6 +630,21 @@ void schwinnic4bike::resistanceFromFTMSAccessory(resistance_t res) {
|
||||
qDebug() << QStringLiteral("resistanceFromFTMSAccessory") << res;
|
||||
}
|
||||
|
||||
double schwinnic4bike::bikeResistanceToPeloton(double bikeResistance) {
|
||||
// brute-force inverse of pelotonToBikeResistance with current settings
|
||||
double bestPeloton = 0;
|
||||
double bestDiff = std::numeric_limits<double>::max();
|
||||
for (int peloton = 0; peloton <= 100; peloton++) {
|
||||
resistance_t converted = pelotonToBikeResistance(peloton);
|
||||
double diff = qFabs((double)converted - bikeResistance);
|
||||
if (diff < bestDiff) {
|
||||
bestDiff = diff;
|
||||
bestPeloton = peloton;
|
||||
}
|
||||
}
|
||||
return bestPeloton;
|
||||
}
|
||||
|
||||
/*
|
||||
uint8_t schwinnic4bike::resistanceFromPowerRequest(uint16_t power) {
|
||||
qDebug() << QStringLiteral("resistanceFromPowerRequest") << Cadence.value() << power;
|
||||
|
||||
@@ -83,6 +83,7 @@ class schwinnic4bike : public bike {
|
||||
void resistanceFromFTMSAccessory(resistance_t res) override;
|
||||
|
||||
private slots:
|
||||
double bikeResistanceToPeloton(double bikeResistance);
|
||||
|
||||
void characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue);
|
||||
void characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue);
|
||||
|
||||
@@ -218,8 +218,9 @@ void tacxneo2::characteristicChanged(const QLowEnergyCharacteristic &characteris
|
||||
uint8_t heart = 0;
|
||||
bool disable_hr_frommachinery =
|
||||
settings.value(QZSettings::heart_ignore_builtin, QZSettings::default_heart_ignore_builtin).toBool();
|
||||
static bool validCadenceFrom2ad2 = false;
|
||||
|
||||
if (characteristic.uuid() == QBluetoothUuid((quint16)0x2A5B)) {
|
||||
if (characteristic.uuid() == QBluetoothUuid((quint16)0x2A5B) && !validCadenceFrom2ad2) {
|
||||
lastPacket = newValue;
|
||||
|
||||
uint8_t index = 1;
|
||||
@@ -599,6 +600,8 @@ void tacxneo2::characteristicChanged(const QLowEnergyCharacteristic &characteris
|
||||
Cadence = ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) |
|
||||
(uint16_t)((uint8_t)newValue.at(index)))) /
|
||||
2.0;
|
||||
if(Cadence.value() > 0)
|
||||
validCadenceFrom2ad2 = true;
|
||||
}
|
||||
index += 2;
|
||||
emit debug(QStringLiteral("Current Cadence: ") + QString::number(Cadence.value()));
|
||||
@@ -750,7 +753,8 @@ void tacxneo2::characteristicChanged(const QLowEnergyCharacteristic &characteris
|
||||
}
|
||||
|
||||
|
||||
if (characteristic.uuid() != QBluetoothUuid((quint16)0xFFF4) && characteristic.uuid() != QBluetoothUuid(QStringLiteral("6e40fec2-b5a3-f393-e0a9-e50e24dcca9e"))) {
|
||||
if (characteristic.uuid() != QBluetoothUuid((quint16)0xFFF4) && characteristic.uuid() != QBluetoothUuid(QStringLiteral("6e40fec2-b5a3-f393-e0a9-e50e24dcca9e")) &&
|
||||
THINK_X == false) { // THINK_X sends the crank revs in the power characteristic
|
||||
if (Cadence.value() > 0) {
|
||||
CrankRevs++;
|
||||
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
|
||||
|
||||
@@ -6150,7 +6150,7 @@ void homeform::update() {
|
||||
QString::number(((elliptical *)bluetoothManager->device())->lastRequestedResistance().value(), 'f', 0));
|
||||
this->target_peloton_resistance->setValue(QString::number(
|
||||
((elliptical *)bluetoothManager->device())->lastRequestedPelotonResistance().value(), 'f', 0));
|
||||
this->resistance->setValue(QString::number(resistance));
|
||||
this->resistance->setValue(QString::number(resistance, 'f', 0));
|
||||
this->peloton_resistance->setSecondLine(
|
||||
QStringLiteral("AVG: ") +
|
||||
QString::number(((elliptical *)bluetoothManager->device())->pelotonResistance().average(), 'f', 0) +
|
||||
|
||||
@@ -241,9 +241,11 @@ void qfit::save(const QString &filename, QList<SessionLine> session, BLUETOOTH_T
|
||||
fit::SessionMesg sessionMesg;
|
||||
sessionMesg.SetTimestamp(session.at(firstRealIndex).time.toSecsSinceEpoch() - 631065600L);
|
||||
sessionMesg.SetStartTime(session.at(firstRealIndex).time.toSecsSinceEpoch() - 631065600L);
|
||||
sessionMesg.SetTotalElapsedTime(session.last().elapsedTime);
|
||||
sessionMesg.SetTotalTimerTime(session.last().time.toSecsSinceEpoch() -
|
||||
session.at(firstRealIndex).time.toSecsSinceEpoch());
|
||||
// Fixed: According to FIT spec, total_elapsed_time includes pauses (real-time duration)
|
||||
// and total_timer_time excludes pauses (active time only)
|
||||
sessionMesg.SetTotalElapsedTime(session.last().time.toSecsSinceEpoch() -
|
||||
session.at(firstRealIndex).time.toSecsSinceEpoch());
|
||||
sessionMesg.SetTotalTimerTime(session.last().elapsedTime);
|
||||
sessionMesg.SetTotalDistance((session.last().distance - startingDistanceOffset) * 1000.0); // meters
|
||||
sessionMesg.SetTotalCalories(session.last().calories);
|
||||
sessionMesg.SetTotalMovingTime(session.last().elapsedTime);
|
||||
|
||||
@@ -225,6 +225,7 @@ const QString QZSettings::nordictrack_treadmill_ultra_le = QStringLiteral("nordi
|
||||
const QString QZSettings::proform_treadmill_carbon_tls = QStringLiteral("proform_treadmill_carbon_tls");
|
||||
const QString QZSettings::proform_treadmill_995i = QStringLiteral("proform_treadmill_995i");
|
||||
const QString QZSettings::nordictrack_series_7 = QStringLiteral("nordictrack_series_7");
|
||||
const QString QZSettings::nordictrack_se7i = QStringLiteral("nordictrack_se7i");
|
||||
const QString QZSettings::toorx_3_0 = QStringLiteral("toorx_3_0");
|
||||
const QString QZSettings::toorx_65s_evo = QStringLiteral("toorx_65s_evo");
|
||||
const QString QZSettings::jtx_fitness_sprint_treadmill = QStringLiteral("jtx_fitness_sprint_treadmill");
|
||||
@@ -573,6 +574,7 @@ const QString QZSettings::computrainer_serialport = QStringLiteral("computrainer
|
||||
const QString QZSettings::default_computrainer_serialport = QStringLiteral("");
|
||||
const QString QZSettings::kettler_usb_serialport = QStringLiteral("kettler_usb_serialport");
|
||||
const QString QZSettings::default_kettler_usb_serialport = QStringLiteral("");
|
||||
const QString QZSettings::kettler_usb_baudrate = QStringLiteral("kettler_usb_baudrate");
|
||||
const QString QZSettings::strava_virtual_activity = QStringLiteral("strava_virtual_activity");
|
||||
const QString QZSettings::powr_sensor_running_cadence_half_on_strava =
|
||||
QStringLiteral("powr_sensor_running_cadence_half_on_strava");
|
||||
@@ -994,7 +996,7 @@ const QString QZSettings::proform_csx210 = QStringLiteral("proform_csx210");
|
||||
const QString QZSettings::skandika_wiri_x2000_protocol = QStringLiteral("skandika_wiri_x2000_protocol");
|
||||
|
||||
|
||||
const uint32_t allSettingsCount = 814;
|
||||
const uint32_t allSettingsCount = 815;
|
||||
|
||||
QVariant allSettings[allSettingsCount][2] = {
|
||||
{QZSettings::cryptoKeySettingsProfiles, QZSettings::default_cryptoKeySettingsProfiles},
|
||||
@@ -1467,6 +1469,7 @@ QVariant allSettings[allSettingsCount][2] = {
|
||||
{QZSettings::ss2k_peloton, QZSettings::default_ss2k_peloton},
|
||||
{QZSettings::computrainer_serialport, QZSettings::default_computrainer_serialport},
|
||||
{QZSettings::kettler_usb_serialport, QZSettings::default_kettler_usb_serialport},
|
||||
{QZSettings::kettler_usb_baudrate, QZSettings::default_kettler_usb_baudrate},
|
||||
{QZSettings::strava_virtual_activity, QZSettings::default_strava_virtual_activity},
|
||||
{QZSettings::powr_sensor_running_cadence_half_on_strava,
|
||||
QZSettings::default_powr_sensor_running_cadence_half_on_strava},
|
||||
|
||||
@@ -692,6 +692,8 @@ class QZSettings {
|
||||
static constexpr bool default_proform_treadmill_995i = false;
|
||||
static const QString nordictrack_series_7;
|
||||
static constexpr bool default_nordictrack_series_7 = false;
|
||||
static const QString nordictrack_se7i;
|
||||
static constexpr bool default_nordictrack_se7i = false;
|
||||
|
||||
static const QString toorx_3_0;
|
||||
static constexpr bool default_toorx_3_0 = false;
|
||||
@@ -1640,6 +1642,8 @@ class QZSettings {
|
||||
|
||||
static const QString kettler_usb_serialport;
|
||||
static const QString default_kettler_usb_serialport;
|
||||
static const QString kettler_usb_baudrate;
|
||||
static constexpr int default_kettler_usb_baudrate = 9600;
|
||||
|
||||
static const QString strava_virtual_activity;
|
||||
static constexpr bool default_strava_virtual_activity = true;
|
||||
|
||||
@@ -1214,7 +1214,9 @@ import Qt.labs.platform 1.1
|
||||
property bool iconcept_ftms_treadmill_inclination_table: false
|
||||
property bool skandika_wiri_x2000_protocol: true
|
||||
property bool nordictrack_series_7: false
|
||||
property string kettler_usb_serialport: ""
|
||||
property string kettler_usb_serialport: ""
|
||||
property int kettler_usb_baudrate: 9600
|
||||
property bool nordictrack_se7i: false
|
||||
}
|
||||
|
||||
|
||||
@@ -4336,6 +4338,35 @@ import Qt.labs.platform 1.1
|
||||
onClicked: { settings.kettler_usb_serialport = kettlerUsbSerialPortTextField.text; window.settings_restart_to_apply = true; toast.show("Setting saved!"); }
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
Label {
|
||||
id: labelKettlerUsbBaudrate
|
||||
text: qsTr("Baudrate:")
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
ComboBox {
|
||||
id: kettlerUsbBaudrateComboBox
|
||||
model: [ "9600", "57600" ]
|
||||
displayText: settings.kettler_usb_baudrate.toString()
|
||||
Layout.fillHeight: false
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
onActivated: {
|
||||
console.log("kettler baudrate combobox activated" + kettlerUsbBaudrateComboBox.currentIndex)
|
||||
displayText = kettlerUsbBaudrateComboBox.currentValue
|
||||
}
|
||||
}
|
||||
Button {
|
||||
id: okKettlerUsbBaudrateButton
|
||||
text: "OK"
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
onClicked: {
|
||||
settings.kettler_usb_baudrate = parseInt(kettlerUsbBaudrateComboBox.displayText);
|
||||
window.settings_restart_to_apply = true;
|
||||
toast.show("Setting saved!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9318,6 +9349,19 @@ import Qt.labs.platform 1.1
|
||||
Layout.fillWidth: true
|
||||
onClicked: { settings.nordictrack_elliptical_c7_5 = checked; window.settings_restart_to_apply = true; }
|
||||
}
|
||||
IndicatorOnlySwitch {
|
||||
text: qsTr("NordicTrack Elliptical SE7i")
|
||||
spacing: 0
|
||||
bottomPadding: 0
|
||||
topPadding: 0
|
||||
rightPadding: 0
|
||||
leftPadding: 0
|
||||
clip: false
|
||||
checked: settings.nordictrack_se7i
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
onClicked: { settings.nordictrack_se7i = checked; window.settings_restart_to_apply = true; }
|
||||
}
|
||||
RowLayout {
|
||||
spacing: 10
|
||||
Label {
|
||||
|
||||
Reference in New Issue
Block a user