Compare commits

...

25 Commits

Author SHA1 Message Date
Roberto Viola
e48af4e864 Update main.yml 2023-07-20 17:39:50 +02:00
Roberto Viola
e990a27f65 Update main.yml 2023-07-20 16:15:17 +02:00
Roberto Viola
4c88304be0 Update main.yml 2023-07-20 16:14:21 +02:00
Roberto Viola
4c1d39d68c Update main.yml 2023-07-20 16:12:38 +02:00
Roberto Viola
efc92f72b2 Update main.yml 2023-07-20 14:37:13 +02:00
Roberto Viola
424e21a8fa Update main.yml 2023-07-20 14:03:14 +02:00
Roberto Viola
51bc2ffb48 Update main.yml 2023-07-20 12:00:28 +02:00
Roberto Viola
7cfd1ba93b Update main.yml 2023-07-20 11:58:34 +02:00
Roberto Viola
c01e5ccb14 Update main.yml 2023-07-20 11:49:08 +02:00
Roberto Viola
dd495f1a76 Merge branch 'master' into android_CI_googleplay 2023-07-20 11:48:52 +02:00
Roberto Viola
458c44758e Android QT Jars patched (#1575)
* Add files via upload

* adding only bluetooth one
2023-07-20 11:45:30 +02:00
Roberto Viola
78e3a33596 Update main.yml 2023-07-20 11:23:17 +02:00
Roberto Viola
77a9fc718a Update main.yml 2023-07-20 11:13:54 +02:00
Roberto Viola
be12859343 No charts when using floating window #1565 2023-07-19 09:53:21 +02:00
Roberto Viola
d201919b55 HR on iPad issue #1529 2023-07-19 09:38:07 +02:00
Roberto Viola
138a42c2e6 fixing CI build 2023-07-18 16:29:08 +02:00
Roberto Viola
bbe69f3f60 fixing build error 2023-07-18 16:02:50 +02:00
Roberto Viola
b95b3a5018 adding gears to wahookickrsnapbike as did for tacxneo
b443b03d49
2023-07-18 15:54:48 +02:00
Roberto Viola
fb0cbb74a5 adding smtp server info on the bottom of the email 2023-07-18 14:28:54 +02:00
Roberto Viola
deed6019ab adding restore purchase button for iOS guidelines 2023-07-18 14:28:33 +02:00
Roberto Viola
7636f768f1 pro form tour de france no reading #1560 (#1566)
* init and update wrote. need to check the force resistance and inclination and read metrics

* finalizing
2023-07-17 15:54:27 +02:00
Roberto Viola
cdf8a95e30 PaddleOCR for Zwift Workout OCR on Windows #1511 2023-07-14 07:39:12 +02:00
Roberto Viola
13389afe77 PaddleOCR for Zwift Workout OCR on Windows #1511 2023-07-14 07:36:16 +02:00
Roberto Viola
8acfb6b764 PaddleOCR for Zwift Workout OCR on Windows #1511 2023-07-14 07:35:13 +02:00
Roberto Viola
4244ce79a0 Ability to play a video in sync with ZWO training file #1562 2023-07-13 20:48:35 +02:00
18 changed files with 269 additions and 35 deletions

View File

@@ -138,8 +138,7 @@ jobs:
cp "C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/libstdc++-6.dll" .
cp ../../../icons/iOS/iTunesArtwork@2x.png .
cp ../../AppxManifest.xml .
cp ../../windows/zwift-incline.py .
cp ../../windows/zwift-workout.py .
cp ../../windows/*.py .
mkdir adb
mkdir python
Copy-Item -Path C:\hostedtoolcache\windows\Python\3.10.11\x64 -Destination python -Recurse
@@ -514,7 +513,7 @@ jobs:
- name: Install Qt Android
uses: jurplel/install-qt-action@v3
with:
version: '5.15.2'
version: '5.15.0'
host: 'linux'
target: 'android'
arch: 'android'
@@ -528,6 +527,9 @@ jobs:
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '11'
- name: patching qt for bluetooth
run: cp qt-patches/android/5.15.0/jar/*.* ${{ github.workspace }}/output/android/Qt/5.15.0/android/jar/
- name: Set Android NDK 21 && build
run: |
@@ -539,6 +541,12 @@ jobs:
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
export ANDROID_NDK="${ANDROID_SDK_ROOT}/ndk-bundle"
export ANDROID_NDK_ROOT="${ANDROID_NDK}"
cd src
echo "#define STRAVA_SECRET_KEY ${{ secrets.strava_secret_key }}" > secret.h
echo "#define SMTP_USERNAME ${{ secrets.smtp_username }}" >> secret.h
echo "#define SMTP_PASSWORD ${{ secrets.smtp_password }}" >> secret.h
echo "#define SMTP_SERVER ${{ secrets.smtp_server }}" >> secret.h
cd ..
ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK
rm -rf /usr/local/lib/android/sdk/ndk/25.1.8937393
@@ -547,6 +555,43 @@ jobs:
- name: Build APK (not usable for production due to unpatched QT library)
run: cd src; androiddeployqt --input android-qdomyos-zwift-deployment-settings.json --output ${{ github.workspace }}/output/android/ --android-platform android-31 --gradle --aab
- uses: r0adkll/sign-android-release@v1
name: Sign app APK
# ID used to access action output
id: sign_app
with:
releaseDirectory: ${{ github.workspace }}/output/android/build/outputs/apk/debug/
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
env:
# override default build-tools version (29.0.3) -- optional
BUILD_TOOLS_VERSION: "30.0.2"
- uses: r0adkll/sign-android-release@v1
name: Sign app AAB
# ID used to access action output
id: sign_aab
with:
releaseDirectory: ${{ github.workspace }}/output/android/build/outputs/bundle/debug/
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
env:
# override default build-tools version (29.0.3) -- optional
BUILD_TOOLS_VERSION: "30.0.2"
- uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
packageName: org.cagnulen.qdomyoszwift
releaseFiles: ${{steps.sign_aab.outputs.signedReleaseFile}}
track: internal
status: draft
inAppUpdatePriority: 2
ios-build:
# The type of runner that the job will run on
runs-on: macos-latest

Binary file not shown.

View File

@@ -317,7 +317,7 @@ HomeForm{
videoPlaybackHalf.seek(rootItem.videoPosition)
videoPlaybackHalf.play()
videoPlaybackHalf.muted = true
videoPlaybackHalf.muted = rootItem.currentCoordinateValid
} else {
videoPlaybackHalf.stop()
}

View File

@@ -93,7 +93,7 @@ Item {
onLinkActivated: Qt.openUrlExternally(link)
}
/*Button {
Button {
id: restoreButton
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
@@ -101,7 +101,8 @@ Item {
text: "Restore Purchases"
onClicked: {
console.log("restoring...");
toast.show("Restoring...");
iapStore.restorePurchases();
}
}*/
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<manifest package="org.cagnulen.qdomyoszwift" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionName="2.13.97" android:versionCode="613" android:installLocation="auto">
<manifest package="org.cagnulen.qdomyoszwift" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionName="2.13.99" android:versionCode="615" android:installLocation="auto">
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS -->

View File

@@ -3202,6 +3202,9 @@ void homeform::StopRequested() {
void homeform::Stop() {
QSettings settings;
m_startRequested = false;
qDebug() << QStringLiteral("Stop pressed - paused") << paused << QStringLiteral("stopped") << stopped;
if (stopped) {
@@ -5959,6 +5962,10 @@ void homeform::sendMail() {
}
}
#ifdef SMTP_SERVER
textMessage += QStringLiteral("\n\nSMTP server: ") + QString(STRINGIFY(SMTP_SERVER));
#endif
text.setText(textMessage);
message.addPart(&text);

View File

@@ -737,7 +737,7 @@ ApplicationWindow {
}
ItemDelegate {
text: "version 2.13.97"
text: "version 2.13.99"
width: parent.width
}

View File

@@ -49,8 +49,7 @@ void proformbike::writeCharacteristic(uint8_t *data, uint8_t data_len, const QSt
gattCommunicationChannelService->writeCharacteristic(gattWriteCharacteristic, *writeBuffer);
if (!disable_log) {
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') +
QStringLiteral(" // ") + info);
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') + QStringLiteral(" // ") + info);
}
loop.exec();
@@ -519,6 +518,9 @@ void proformbike::update() {
.toBool();
bool proform_bike_sb =
settings.value(QZSettings::proform_bike_sb, QZSettings::default_proform_bike_sb).toBool();
bool proform_bike_PFEVEX71316_1 =
settings.value(QZSettings::proform_bike_PFEVEX71316_1, QZSettings::default_proform_bike_PFEVEX71316_1)
.toBool();
uint8_t noOpData1[] = {0xfe, 0x02, 0x19, 0x03};
uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x07, 0x15, 0x02, 0x00,
@@ -587,6 +589,16 @@ void proformbike::update() {
0x0d, 0x02, 0x00, 0x07, 0xbc, 0x90, 0x70,
0x00, 0x00, 0x00, 0x40, 0x19, 0x00};
// proform_bike_PFEVEX71316_1
uint8_t noOpData2_proform_bike_PFEVEX71316_1[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x08, 0x15, 0x02, 0x00,
0x0f, 0xb6, 0x10, 0x30, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t noOpData3_proform_bike_PFEVEX71316_1[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t noOpData5_proform_bike_PFEVEX71316_1[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x08, 0x13, 0x02, 0x00,
0x0d, 0x09, 0x8e, 0x41, 0x00, 0x00, 0x40, 0x50, 0x00, 0x80};
uint8_t noOpData6_proform_bike_PFEVEX71316_1[] = {0xff, 0x05, 0x18, 0x00, 0x00, 0x81, 0xab, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
switch (counterPoll) {
case 0:
if (nordictrack_gx_2_7 || proform_hybrid_trainer_PFEL03815 || proform_bike_sb) {
@@ -613,6 +625,9 @@ void proformbike::update() {
else if (proform_bike_sb)
writeCharacteristic(noOpData2_proform_bike_sb, sizeof(noOpData2_proform_bike_sb),
QStringLiteral("noOp"));
else if (proform_bike_PFEVEX71316_1)
writeCharacteristic(noOpData2_proform_bike_PFEVEX71316_1, sizeof(noOpData2_proform_bike_PFEVEX71316_1),
QStringLiteral("noOp"));
else
writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("noOp"));
break;
@@ -634,6 +649,9 @@ void proformbike::update() {
else if (proform_bike_sb)
writeCharacteristic(noOpData3_proform_bike_sb, sizeof(noOpData3_proform_bike_sb),
QStringLiteral("noOp"));
else if (proform_bike_PFEVEX71316_1)
writeCharacteristic(noOpData3_proform_bike_PFEVEX71316_1, sizeof(noOpData3_proform_bike_PFEVEX71316_1),
QStringLiteral("noOp"));
else
writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("noOp"));
break;
@@ -665,6 +683,9 @@ void proformbike::update() {
} else if (proform_bike_sb)
writeCharacteristic(noOpData5_proform_bike_sb, sizeof(noOpData5_proform_bike_sb),
QStringLiteral("noOp"));
else if (proform_bike_PFEVEX71316_1)
writeCharacteristic(noOpData5_proform_bike_PFEVEX71316_1, sizeof(noOpData5_proform_bike_PFEVEX71316_1),
QStringLiteral("noOp"));
else
writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("noOp"));
break;
@@ -677,6 +698,9 @@ void proformbike::update() {
else if (proform_cycle_trainer_400)
writeCharacteristic(noOpData6_proform_cycle_trainer_400, sizeof(noOpData6_proform_cycle_trainer_400),
QStringLiteral("noOp"));
else if (proform_bike_PFEVEX71316_1)
writeCharacteristic(noOpData6_proform_bike_PFEVEX71316_1, sizeof(noOpData6_proform_bike_PFEVEX71316_1),
QStringLiteral("noOp"));
else
writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("noOp"));
break;
@@ -704,7 +728,8 @@ void proformbike::update() {
counterPoll++;
if (counterPoll > 6) {
counterPoll = 0;
} else if (counterPoll == 6 && (proform_tour_de_france_clc || proform_cycle_trainer_400) &&
} else if (counterPoll == 6 &&
(proform_tour_de_france_clc || proform_cycle_trainer_400 || proform_bike_PFEVEX71316_1) &&
requestResistance == -1) {
// this bike sends the frame noOpData7 only when it needs to change the resistance
counterPoll = 0;
@@ -818,6 +843,8 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte
.value(QZSettings::proform_hybrid_trainer_PFEL03815, QZSettings::default_proform_hybrid_trainer_PFEL03815)
.toBool();
bool proform_bike_sb = settings.value(QZSettings::proform_bike_sb, QZSettings::default_proform_bike_sb).toBool();
bool proform_bike_PFEVEX71316_1 =
settings.value(QZSettings::proform_bike_PFEVEX71316_1, QZSettings::default_proform_bike_PFEVEX71316_1).toBool();
emit debug(QStringLiteral(" << ") + newValue.toHex(' '));
@@ -864,6 +891,43 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte
Cadence = ((uint8_t)newValue.at(2));
}
}
} else if (proform_bike_PFEVEX71316_1) {
if (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) == 0x2f && newValue.at(6) == 0x08 &&
newValue.at(7) == 0x2f && newValue.at(8) == 0x02 && newValue.at(9) == 0x02 && newValue.at(10) == 0x00 &&
newValue.at(11) == 0x00 && newValue.at(14) == 0x5a) {
m_watt = ((uint16_t)(((uint8_t)newValue.at(13)) << 8) + (uint16_t)((uint8_t)newValue.at(12)));
} else if (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) == 0x2f && newValue.at(6) == 0x08 && newValue.at(7) == 0x2f &&
newValue.at(8) == 0x02 && newValue.at(9) == 0x02 && newValue.at(10) != 0x00 &&
newValue.at(11) != 0x00 && newValue.at(14) == 0x5a) {
if (!settings.value(QZSettings::speed_power_based, QZSettings::default_speed_power_based).toBool()) {
Speed = ((double)((uint16_t)(((uint8_t)newValue.at(13)) << 8) + (uint16_t)((uint8_t)newValue.at(12))) /
100.0);
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
double incline =
((double)((int16_t)(((int8_t)newValue.at(11)) << 8) + (int16_t)((uint8_t)newValue.at(10))) / 100.0);
if ((uint16_t)(qAbs(incline) * 10) % 5 == 0) {
Inclination = incline;
emit debug(QStringLiteral("Current Inclination: ") + QString::number(incline));
} else {
emit debug(QStringLiteral("Filtering bad inclination"));
}
if (settings.value(QZSettings::cadence_sensor_name, QZSettings::default_cadence_sensor_name)
.toString()
.startsWith(QStringLiteral("Disabled"))) {
Cadence = ((uint8_t)newValue.at(18));
}
}
} else {
if (newValue.length() != 20 || newValue.at(0) != 0x00 || newValue.at(1) != 0x12 || newValue.at(2) != 0x01 ||
@@ -1268,7 +1332,9 @@ void proformbike::btinit() {
QThread::msleep(400);
writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false);
QThread::msleep(400);
} else if (settings.value(QZSettings::proform_tdf_10, QZSettings::default_proform_tdf_10).toBool()) {
} else if (settings.value(QZSettings::proform_tdf_10, QZSettings::default_proform_tdf_10).toBool() ||
settings.value(QZSettings::proform_bike_PFEVEX71316_1, QZSettings::default_proform_bike_PFEVEX71316_1)
.toBool()) {
max_resistance = 26;
uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02};
@@ -1314,19 +1380,36 @@ void proformbike::btinit() {
writeCharacteristic(initData9, sizeof(initData9), QStringLiteral("init"), false, false);
QThread::msleep(400);
uint8_t initData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x08, 0x28, 0x90, 0x04,
0x00, 0x40, 0x0c, 0xca, 0x9e, 0x64, 0x38, 0xf6, 0xda, 0xa8};
uint8_t initData11[] = {0x01, 0x12, 0x74, 0x42, 0x26, 0x0c, 0xf0, 0xae, 0xb2, 0x90,
0x7c, 0x5a, 0x2e, 0x34, 0x08, 0xe6, 0xea, 0xf8, 0xc4, 0xd2};
uint8_t initData12[] = {0xff, 0x08, 0xd6, 0xdc, 0xe0, 0x88, 0x02, 0x00, 0x00, 0x0e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (settings.value(QZSettings::proform_bike_PFEVEX71316_1, QZSettings::default_proform_bike_PFEVEX71316_1)
.toBool()) {
uint8_t initData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x08, 0x28, 0x90, 0x04,
0x00, 0xc1, 0x58, 0xfd, 0x90, 0x31, 0xd0, 0x75, 0x28, 0xc1};
uint8_t initData11[] = {0x01, 0x12, 0x78, 0x2d, 0xc0, 0x71, 0x20, 0xf5, 0x88, 0x41,
0x18, 0xdd, 0x90, 0x51, 0x10, 0xd5, 0x88, 0x41, 0x38, 0xed};
uint8_t initData12[] = {0xff, 0x08, 0xa0, 0x91, 0x40, 0x88, 0x02, 0x00, 0x00, 0x21,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
writeCharacteristic(initData10, sizeof(initData10), QStringLiteral("init"), false, false);
QThread::msleep(400);
writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false);
QThread::msleep(400);
writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false);
QThread::msleep(400);
writeCharacteristic(initData10, sizeof(initData10), QStringLiteral("init"), false, false);
QThread::msleep(400);
writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false);
QThread::msleep(400);
writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false);
QThread::msleep(400);
} else {
uint8_t initData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x08, 0x28, 0x90, 0x04,
0x00, 0x40, 0x0c, 0xca, 0x9e, 0x64, 0x38, 0xf6, 0xda, 0xa8};
uint8_t initData11[] = {0x01, 0x12, 0x74, 0x42, 0x26, 0x0c, 0xf0, 0xae, 0xb2, 0x90,
0x7c, 0x5a, 0x2e, 0x34, 0x08, 0xe6, 0xea, 0xf8, 0xc4, 0xd2};
uint8_t initData12[] = {0xff, 0x08, 0xd6, 0xdc, 0xe0, 0x88, 0x02, 0x00, 0x00, 0x0e,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
writeCharacteristic(initData10, sizeof(initData10), QStringLiteral("init"), false, false);
QThread::msleep(400);
writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false);
QThread::msleep(400);
writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false);
QThread::msleep(400);
}
} else {
uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02};

View File

@@ -812,4 +812,4 @@ INCLUDEPATH += purchasing/inapp
WINRT_MANIFEST = AppxManifest.xml
VERSION = 2.13.97
VERSION = 2.13.99

View File

@@ -663,8 +663,10 @@ const QString QZSettings::proform_bike_sb = QStringLiteral("proform_bike_sb");
const QString QZSettings::fakedevice_rower = QStringLiteral("fakedevice_rower");
const QString QZSettings::zwift_ocr_climb_portal = QStringLiteral("zwift_ocr_climb_portal");
const QString QZSettings::poll_device_time = QStringLiteral("poll_device_time");
const QString QZSettings::proform_bike_PFEVEX71316_1 = QStringLiteral("proform_bike_PFEVEX71316_1");
const QString QZSettings::schwinn_bike_resistance_v3 = QStringLiteral("schwinn_bike_resistance_v3");
const uint32_t allSettingsCount = 555;
const uint32_t allSettingsCount = 557;
QVariant allSettings[allSettingsCount][2] = {
{QZSettings::cryptoKeySettingsProfiles, QZSettings::default_cryptoKeySettingsProfiles},
@@ -1226,6 +1228,8 @@ QVariant allSettings[allSettingsCount][2] = {
{QZSettings::fakedevice_rower, QZSettings::default_fakedevice_rower},
{QZSettings::zwift_ocr_climb_portal, QZSettings::default_zwift_ocr_climb_portal},
{QZSettings::poll_device_time, QZSettings::default_poll_device_time},
{QZSettings::proform_bike_PFEVEX71316_1, QZSettings::default_proform_bike_PFEVEX71316_1},
{QZSettings::schwinn_bike_resistance_v3, QZSettings::default_schwinn_bike_resistance_v3},
};
void QZSettings::qDebugAllSettings(bool showDefaults) {

View File

@@ -1860,6 +1860,12 @@ class QZSettings {
static const QString poll_device_time;
static constexpr int default_poll_device_time = 200;
static const QString proform_bike_PFEVEX71316_1;
static constexpr bool default_proform_bike_PFEVEX71316_1 = false;
static const QString schwinn_bike_resistance_v3;
static constexpr bool default_schwinn_bike_resistance_v3 = false;
/**
* @brief Write the QSettings values using the constants from this namespace.
* @param showDefaults Optionally indicates if the default should be shown with the key.

View File

@@ -555,6 +555,8 @@ resistance_t schwinnic4bike::pelotonToBikeResistance(int pelotonResistance) {
QSettings settings;
bool schwinn_bike_resistance_v2 =
settings.value(QZSettings::schwinn_bike_resistance_v2, QZSettings::default_schwinn_bike_resistance_v2).toBool();
bool schwinn_bike_resistance_v3 =
settings.value(QZSettings::schwinn_bike_resistance_v3, QZSettings::default_schwinn_bike_resistance_v3).toBool();
if (!schwinn_bike_resistance_v2) {
if (pelotonResistance > 54)
return pelotonResistance;
@@ -563,6 +565,12 @@ resistance_t schwinnic4bike::pelotonToBikeResistance(int pelotonResistance) {
// y = 0,04x2 - 1,32x + 11,8
return ((0.04 * pow(pelotonResistance, 2)) - (1.32 * pelotonResistance) + 11.8);
} else if (schwinn_bike_resistance_v3) {
// y = 0,0007x3 - 0,0763x2 + 4,1619x - 75,788
if (pelotonResistance < 30)
return 0;
return qRound((0.0007 * pow(pelotonResistance, 3)) - (0.0763 * pow(pelotonResistance, 2)) + (4.1619 * pelotonResistance) + 75.788);
} else {
if (pelotonResistance > 20)
return (((double)pelotonResistance - 20.0) * 1.25);

View File

@@ -807,6 +807,10 @@ import QtQuick.Dialogs 1.0
// from version 2.13.96
property bool zwift_ocr_climb_portal: false
property int poll_device_time: 200
// from version 2.13.99
property bool proform_bike_PFEVEX71316_1: false
property bool schwinn_bike_resistance_v3: false
}
function paddingZeros(text, limit) {
@@ -2211,7 +2215,7 @@ import QtQuick.Dialogs 1.0
}
SwitchDelegate {
id: schwinnBikeResistanceV2Delegate
text: qsTr("Resistance Alternative Calc.")
text: qsTr("Res. Alternative Calc. v2")
spacing: 0
bottomPadding: 0
topPadding: 0
@@ -2223,6 +2227,19 @@ import QtQuick.Dialogs 1.0
Layout.fillWidth: true
onClicked: settings.schwinn_bike_resistance_v2 = checked
}
SwitchDelegate {
text: qsTr("Res. Alternative Calc. v3")
spacing: 0
bottomPadding: 0
topPadding: 0
rightPadding: 0
leftPadding: 0
clip: false
checked: settings.schwinn_bike_resistance_v3
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillWidth: true
onClicked: settings.schwinn_bike_resistance_v3 = checked
}
RowLayout {
spacing: 10
Label {
@@ -2804,6 +2821,19 @@ import QtQuick.Dialogs 1.0
Layout.fillWidth: true
onClicked: { settings.proform_tdf_10 = checked; window.settings_restart_to_apply = true; }
}
SwitchDelegate {
text: qsTr("TDF 1.0 PFEVEX71316.1")
spacing: 0
bottomPadding: 0
topPadding: 0
rightPadding: 0
leftPadding: 0
clip: false
checked: settings.proform_bike_PFEVEX71316_1
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillWidth: true
onClicked: { settings.proform_bike_PFEVEX71316_1 = checked; window.settings_restart_to_apply = true; }
}
SwitchDelegate {
id: nordictrackGX27odelegate
text: qsTr("NordicTrack GX 2.7")
@@ -4166,7 +4196,7 @@ import QtQuick.Dialogs 1.0
}
SwitchDelegate {
text: qsTr("Zwift Treadmill Auto Inclination")
text: qsTr("Zwift Treadmill Climb Portal")
spacing: 0
bottomPadding: 0
topPadding: 0

View File

@@ -234,7 +234,10 @@ void wahookickrsnapbike::update() {
uint8_t b[20];
memcpy(b, a.constData(), a.length());
writeCharacteristic(b, a.length(), "setResistance", false, true);
} else if (virtualBike && virtualBike->ftmsDeviceConnected() && lastGearValue != gears()) {
inclinationChanged(lastGrade, lastGrade);
}
lastGearValue = gears();
requestResistance = -1;
}
if (requestStart != -1) {
@@ -789,8 +792,9 @@ void wahookickrsnapbike::controllerStateChanged(QLowEnergyController::Controller
void wahookickrsnapbike::inclinationChanged(double grade, double percentage) {
Q_UNUSED(percentage);
lastGrade = grade;
emit debug(QStringLiteral("writing inclination ") + QString::number(grade));
QByteArray a = setSimGrade(grade);
QByteArray a = setSimGrade(grade + gears());
uint8_t b[20];
memcpy(b, a.constData(), a.length());
writeCharacteristic(b, a.length(), "setSimGrade", false, true);

View File

@@ -83,6 +83,8 @@ class wahookickrsnapbike : public bike {
uint8_t sec1Update = 0;
QByteArray lastPacket;
double lastGearValue = -1;
double lastGrade = 0;
QDateTime lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
QDateTime lastGoodCadence = QDateTime::currentDateTime();
uint8_t firstStateChanged = 0;

View File

@@ -23,10 +23,13 @@ screenshot_np = np.array(screenshot)
# Crop image to incline area
screenwidth, screenheight = screenshot.size
# Values for Zwift climb portal incline
col1 = int(screenwidth/3000 * 2822)
row1 = int(screenheight/2000 * 218)
col2 = int(screenwidth/3000 * 2980)
row2 = int(screenheight/2000 * 302)
cropped_np = screenshot_np[row1:row2, col1:col2]
# Convert numpy array to PIL image

View File

@@ -23,10 +23,13 @@ screenshot_np = np.array(screenshot)
# Crop image to incline area
screenwidth, screenheight = screenshot.size
# Values for Zwift regular incline
col1 = int(screenwidth/3000 * 2800)
row1 = int(screenheight/2000 * 75)
col2 = screenwidth
row2 = int(screenheight/2000 * 200)
cropped_np = screenshot_np[row1:row2, col1:col2]
# Convert numpy array to PIL image

View File

@@ -67,6 +67,7 @@ void zwiftworkout::convertTag(double thresholdSecPerKm, const QString &sportType
double OnPower = 1;
double OffPower = 1;
int Pace = -1;
int Cadence = -1;
repeat = va_arg(args, uint32_t);
if (repeat <= 0)
repeat = 1;
@@ -75,6 +76,7 @@ void zwiftworkout::convertTag(double thresholdSecPerKm, const QString &sportType
OnPower = va_arg(args, double);
OffPower = va_arg(args, double);
Pace = va_arg(args, int);
Cadence = va_arg(args, int);
for (uint32_t i = 0; i < repeat; i++) {
trainrow row;
if (!durationAsDistance(sportType, durationType))
@@ -100,6 +102,8 @@ void zwiftworkout::convertTag(double thresholdSecPerKm, const QString &sportType
} else {
row.power = OffPower * settings.value(QZSettings::ftp, QZSettings::default_ftp).toDouble();
}
if(Cadence != -1)
row.cadence = Cadence;
qDebug() << "TrainRow" << row.toString();
list.append(row);
}
@@ -108,10 +112,12 @@ void zwiftworkout::convertTag(double thresholdSecPerKm, const QString &sportType
double PowerLow = 1;
double PowerHigh = 1;
int Pace = -1;
int Cadence = -1;
Duration = va_arg(args, uint32_t);
PowerLow = va_arg(args, double);
PowerHigh = va_arg(args, double);
Pace = va_arg(args, int);
Cadence = va_arg(args, int);
if (sportType.toLower().contains(QStringLiteral("run")) && !durationAsDistance(sportType, durationType)) {
double speed = speedFromPace(Pace);
int speedDelta = qAbs(qCeil((((60.0 / speed) * 60.0) * (PowerHigh - PowerLow)) * 10)) + 1;
@@ -147,6 +153,8 @@ void zwiftworkout::convertTag(double thresholdSecPerKm, const QString &sportType
} else {
row.distance = 0.001;
}
if(Cadence != -1)
row.cadence = Cadence;
if (PowerHigh > PowerLow) {
if (!sportType.toLower().contains(QStringLiteral("run"))) {
row.power = (PowerLow + (((PowerHigh - PowerLow) / Duration) * i)) *
@@ -187,12 +195,14 @@ void zwiftworkout::convertTag(double thresholdSecPerKm, const QString &sportType
double Power = 1;
double Incline = -100;
int Pace = -1;
int Cadence = -1;
trainrow row;
Duration = va_arg(args, uint32_t);
Power = va_arg(args, double);
Pace = va_arg(args, int);
Incline = va_arg(args, double);
Cadence = va_arg(args, int);
if (sportType.toLower().contains(QStringLiteral("run")) && Duration != 1) {
if (thresholdSecPerKm != 0) {
@@ -216,6 +226,9 @@ void zwiftworkout::convertTag(double thresholdSecPerKm, const QString &sportType
row.inclination = Incline * 100;
}
if(Cadence != -1)
row.cadence = Cadence;
qDebug() << "TrainRow" << row.toString();
list.append(row);
}
@@ -264,6 +277,7 @@ QList<trainrow> zwiftworkout::loadJSON(const QString &input, QString *descriptio
double OnPower = 1;
double OffPower = 1;
int Pace = -1;
int Cadence = -1;
repeat = element[QStringLiteral("Repeat")].toInt();
if (!repeat)
repeat = 1;
@@ -274,8 +288,11 @@ QList<trainrow> zwiftworkout::loadJSON(const QString &input, QString *descriptio
if (element.contains(QStringLiteral("pace"))) {
Pace = element[QStringLiteral("pace")].toInt();
}
if (element.contains(QStringLiteral("Cadence"))) {
Cadence = element[QStringLiteral("Cadence")].toInt();
}
convertTag(0.0, sportType, durationType, list, type.toUtf8().constData(), repeat, OnDuration,
OffDuration, OnPower, OffPower, Pace);
OffDuration, OnPower, OffPower, Pace, Cadence);
} else if (type == QStringLiteral("FreeRide")) {
uint32_t Duration = 1;
// double FlatRoad = 1;
@@ -288,19 +305,24 @@ QList<trainrow> zwiftworkout::loadJSON(const QString &input, QString *descriptio
double PowerLow = 1;
double PowerHigh = 1;
int Pace = -1;
int Cadence = -1;
Duration = element[QStringLiteral("Duration")].toDouble();
PowerLow = element[QStringLiteral("PowerLow")].toDouble();
PowerHigh = element[QStringLiteral("PowerHigh")].toDouble();
if (element.contains(QStringLiteral("pace"))) {
Pace = element[QStringLiteral("pace")].toInt();
}
if (element.contains(QStringLiteral("Cadence"))) {
Cadence = element[QStringLiteral("Cadence")].toInt();
}
convertTag(0.0, sportType, durationType, list, type.toUtf8().constData(), Duration, PowerLow,
PowerHigh, Pace);
PowerHigh, Pace, Cadence);
} else if (type == QStringLiteral("SteadyState")) {
uint32_t Duration = 1;
double Power = 1;
int Pace = -1;
double Incline = -100;
int Cadence = -1;
Duration = element[QStringLiteral("Duration")].toDouble();
if (element.contains(QStringLiteral("pace"))) {
@@ -313,7 +335,10 @@ QList<trainrow> zwiftworkout::loadJSON(const QString &input, QString *descriptio
if (element.contains(QStringLiteral("Incline"))) {
Incline = element[QStringLiteral("Incline")].toDouble();
}
convertTag(0.0, sportType, durationType, list, type.toUtf8().constData(), Duration, Power, Pace, Incline);
if (element.contains(QStringLiteral("Cadence"))) {
Cadence = element[QStringLiteral("Cadence")].toInt();
}
convertTag(0.0, sportType, durationType, list, type.toUtf8().constData(), Duration, Power, Pace, Incline, Cadence);
}
}
}
@@ -363,6 +388,7 @@ QList<trainrow> zwiftworkout::load(const QByteArray &input, QString *description
double OnPower = 1;
double OffPower = 1;
int Pace = -1;
int Cadence = -1;
if (atts.hasAttribute(QStringLiteral("Repeat"))) {
repeat = atts.value(QStringLiteral("Repeat")).toUInt();
}
@@ -381,9 +407,12 @@ QList<trainrow> zwiftworkout::load(const QByteArray &input, QString *description
if (atts.hasAttribute(QStringLiteral("pace"))) {
Pace = atts.value(QStringLiteral("pace")).toUInt();
}
if (atts.hasAttribute(QStringLiteral("Cadence"))) {
Cadence = atts.value(QStringLiteral("Cadence")).toUInt();
}
convertTag(thresholdSecPerKm, sportType, durationType, list, name.toUtf8().constData(), repeat,
OnDuration, OffDuration, OnPower, OffPower, Pace);
OnDuration, OffDuration, OnPower, OffPower, Pace, Cadence);
} else if (name.contains(QStringLiteral("FreeRide"))) {
uint32_t Duration = 1;
// double FlatRoad = 1;
@@ -403,6 +432,8 @@ QList<trainrow> zwiftworkout::load(const QByteArray &input, QString *description
double PowerLow = 1;
double PowerHigh = 1;
int Pace = -1;
int Cadence = -1;
if (atts.hasAttribute(QStringLiteral("Duration"))) {
Duration = atts.value(QStringLiteral("Duration")).toDouble();
}
@@ -415,14 +446,18 @@ QList<trainrow> zwiftworkout::load(const QByteArray &input, QString *description
if (atts.hasAttribute(QStringLiteral("pace"))) {
Pace = atts.value(QStringLiteral("pace")).toUInt();
}
if (atts.hasAttribute(QStringLiteral("Cadence"))) {
Cadence = atts.value(QStringLiteral("Cadence")).toUInt();
}
convertTag(thresholdSecPerKm, sportType, durationType, list, name.toUtf8().constData(), Duration,
PowerLow, PowerHigh, Pace);
PowerLow, PowerHigh, Pace, Cadence);
} else if (name.contains(QStringLiteral("SteadyState"))) {
uint32_t Duration = 1;
double Power = 1;
int Pace = -1;
double Incline = -100;
int Cadence = -1;
if (atts.hasAttribute(QStringLiteral("Duration"))) {
Duration = atts.value(QStringLiteral("Duration")).toDouble();
@@ -439,8 +474,11 @@ QList<trainrow> zwiftworkout::load(const QByteArray &input, QString *description
if (atts.hasAttribute(QStringLiteral("Incline"))) {
Incline = atts.value(QStringLiteral("Incline")).toDouble();
}
if (atts.hasAttribute(QStringLiteral("Cadence"))) {
Cadence = atts.value(QStringLiteral("Cadence")).toUInt();
}
convertTag(thresholdSecPerKm, sportType, durationType, list, name.toUtf8().constData(), Duration, Power,
Pace, Incline);
Pace, Incline, Cadence);
}
}
}