diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b9c9cff61..156a9fd98 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -196,6 +196,54 @@ jobs: path: release.zip if: ${{ ! matrix.config.python }} + # - name: Exit if not on master branch + # if: github.ref == 'refs/heads/main' + # run: exit 1 + + # - uses: actions/checkout@v3 + # with: + # fetch-depth: 0 # Required due to the way Git works, without it this action won't be able to find any or the correct tags + + # - name: Get previous tag + # id: previoustag + # uses: 'WyriHaximus/github-action-get-previous-tag@v1' + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # - name: Create Release + # if: ${{ ! matrix.config.python }} + # id: create_release + # uses: actions/create-release@v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # tag_name: ${{ steps.previoustag.outputs.tag }} + # release_name: Release ${{ steps.previoustag.outputs.tag }} + # draft: false + # prerelease: false + + # - name: upload windows artifact + # uses: actions/upload-release-asset@v1 + # if: ${{ ! matrix.config.python }} + # env: + # GITHUB_TOKEN: ${{ github.token }} + # with: + # upload_url: ${{ steps.create_release.outputs.upload_url }} + # asset_path: release.zip + # asset_name: windows-binary-no-python.zip + # asset_content_type: application/zip + + # - name: upload windows artifact + # uses: actions/upload-release-asset@v1 + # if: ${{ matrix.config.python }} + # env: + # GITHUB_TOKEN: ${{ github.token }} + # with: + # upload_url: ${{ steps.create_release.outputs.upload_url }} + # asset_path: release.zip + # asset_name: windows-binary.zip + # asset_content_type: application/zip + # window-steam-build: # runs-on: windows-latest # @@ -280,6 +328,19 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: + - name: release + uses: actions/create-release@v1 + if: startsWith(github.ref, 'refs/tags/') + id: create_release + with: + draft: false + prerelease: false + release_name: ${{ steps.version.outputs.version }} + tag_name: ${{ github.ref }} + body_path: CHANGELOG.md + env: + GITHUB_TOKEN: ${{ github.token }} + # - name: Cache Qt Linux Desktop # id: cache-qt-linux-desktop # uses: actions/cache@v1 @@ -583,6 +644,20 @@ jobs: name: fdroid-android-trial path: ${{ github.workspace }}/output/android/build/outputs/apk/debug/ + # - name: Exit if not on master branch + # if: github.ref == 'refs/heads/main' + # run: exit 1 + + # - name: upload windows artifact + # uses: actions/upload-release-asset@v1 + # env: + # GITHUB_TOKEN: ${{ github.token }} + # with: + # upload_url: ${{ steps.create_release.outputs.upload_url }} + # asset_path: ${{ github.workspace }}/output/android/build/outputs/apk/debug/android-debug.apk + # asset_name: fdroid-android-trial.zip + # asset_content_type: application/zip + ios-build: # The type of runner that the job will run on runs-on: macos-latest diff --git a/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/qdomyoszwift.xcodeproj/project.pbxproj b/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/qdomyoszwift.xcodeproj/project.pbxproj index c26d6885c..3a2fc18e2 100644 --- a/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/qdomyoszwift.xcodeproj/project.pbxproj +++ b/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/qdomyoszwift.xcodeproj/project.pbxproj @@ -3666,7 +3666,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 643; + CURRENT_PROJECT_VERSION = 645; DEVELOPMENT_TEAM = 6335M7T29D; ENABLE_BITCODE = NO; HEADER_SEARCH_PATHS = ( @@ -3834,7 +3834,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 643; + CURRENT_PROJECT_VERSION = 645; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 6335M7T29D; ENABLE_BITCODE = NO; @@ -4038,7 +4038,7 @@ CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 643; + CURRENT_PROJECT_VERSION = 645; DEVELOPMENT_TEAM = 6335M7T29D; ENABLE_BITCODE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -4134,7 +4134,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 643; + CURRENT_PROJECT_VERSION = 645; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 6335M7T29D; ENABLE_BITCODE = YES; @@ -4226,7 +4226,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 643; + CURRENT_PROJECT_VERSION = 645; DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\""; ENABLE_BITCODE = YES; ENABLE_PREVIEWS = YES; @@ -4340,7 +4340,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 643; + CURRENT_PROJECT_VERSION = 645; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\""; ENABLE_BITCODE = YES; diff --git a/src/Home.qml b/src/Home.qml index bbd537712..176481783 100644 --- a/src/Home.qml +++ b/src/Home.qml @@ -291,72 +291,75 @@ HomeForm{ } footer: - - Rectangle { - id: chartFooterRectangle - visible: rootItem.chartFooterVisible + Item { width: parent.width - height: parent.height / 4 - ChartFooter { - anchors.fill: parent + height: (rootItem.chartFooterVisible ? parent.height / 4 : parent.height / 2) + anchors.top: gridView.bottom + visible: rootItem.chartFooterVisible || rootItem.videoVisible + + Rectangle { + id: chartFooterRectangle visible: rootItem.chartFooterVisible + anchors.fill: parent + ChartFooter { + anchors.fill: parent + visible: rootItem.chartFooterVisible + } } - } - Rectangle { - objectName: "footerrectangle" - visible: rootItem.videoVisible - anchors.top: gridView.bottom - width: parent.width - height: parent.height / 2 - // Removed Timer, Play/Pause/Resume is now done via Homeform.cpp - /* - Timer { - id: pauseTimer - interval: 1000; running: true; repeat: true - onTriggered: { if(visible == true) { (rootItem.currentSpeed > 0 ? - videoPlaybackHalf.play() : - videoPlaybackHalf.pause()) } } - } - */ - - onVisibleChanged: { - if(visible === true) { - console.log("mediaPlayer onCompleted: " + rootItem.videoPath) - console.log("videoRate: " + rootItem.videoRate) - videoPlaybackHalf.source = rootItem.videoPath - //videoPlaybackHalf.playbackRate = rootItem.videoRate - - videoPlaybackHalf.seek(rootItem.videoPosition) - videoPlaybackHalf.play() - videoPlaybackHalf.muted = rootItem.currentCoordinateValid - } else { - videoPlaybackHalf.stop() + Rectangle { + objectName: "footerrectangle" + visible: rootItem.videoVisible + anchors.fill: parent + // Removed Timer, Play/Pause/Resume is now done via Homeform.cpp + /* + Timer { + id: pauseTimer + interval: 1000; running: true; repeat: true + onTriggered: { if(visible == true) { (rootItem.currentSpeed > 0 ? + videoPlaybackHalf.play() : + videoPlaybackHalf.pause()) } } } + */ + + onVisibleChanged: { + if(visible === true) { + console.log("mediaPlayer onCompleted: " + rootItem.videoPath) + console.log("videoRate: " + rootItem.videoRate) + videoPlaybackHalf.source = rootItem.videoPath + //videoPlaybackHalf.playbackRate = rootItem.videoRate + + videoPlaybackHalf.seek(rootItem.videoPosition) + videoPlaybackHalf.play() + videoPlaybackHalf.muted = rootItem.currentCoordinateValid + } else { + videoPlaybackHalf.stop() + } - } + } - MediaPlayer { - id: videoPlaybackHalf - objectName: "videoplaybackhalf" - autoPlay: false - playbackRate: rootItem.videoRate + MediaPlayer { + id: videoPlaybackHalf + objectName: "videoplaybackhalf" + autoPlay: false + playbackRate: rootItem.videoRate - onError: { - if (videoPlaybackHalf.NoError !== error) { - console.log("[qmlvideo] VideoItem.onError error " + error + " errorString " + errorString) + onError: { + if (videoPlaybackHalf.NoError !== error) { + console.log("[qmlvideo] VideoItem.onError error " + error + " errorString " + errorString) + } } - } - } + } - VideoOutput { - id:videoPlayer - anchors.fill: parent - source: videoPlaybackHalf - } + VideoOutput { + id:videoPlayer + anchors.fill: parent + source: videoPlaybackHalf + } + } - } + } MouseArea { property int currentId: -1 // Original position in model diff --git a/src/android/AndroidManifest.xml b/src/android/AndroidManifest.xml index 5d8cee0fc..e78c867b8 100644 --- a/src/android/AndroidManifest.xml +++ b/src/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/src/bluetooth.cpp b/src/bluetooth.cpp index 8a9890bdc..55b893c1b 100644 --- a/src/bluetooth.cpp +++ b/src/bluetooth.cpp @@ -1029,6 +1029,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { b.name().toUpper().startsWith(QStringLiteral("WALKINGPAD")) || !b.name().toUpper().compare(QStringLiteral("RE")) || // just "RE" b.name().toUpper().startsWith(QStringLiteral("KS-H")) || + b.name().toUpper().startsWith(QStringLiteral("KS-BLC")) || // Walkingpad C2 #1672 b.name().toUpper().startsWith( QStringLiteral("KS-BLR"))) && // Treadmill KingSmith WalkingPad R2 Pro KS-HCR1AA !kingsmithR1ProTreadmill && @@ -1303,6 +1304,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { npeCableBike->deviceDiscovered(b); this->signalBluetoothDeviceConnected(npeCableBike); } else if (((b.name().startsWith("FS-") && hammerRacerS) || + (b.name().toUpper().startsWith("DI") && b.name().length() == 2) || // Elite smart trainer #1682 (b.name().toUpper().startsWith("DHZ-")) || // JK fitness 577 (b.name().toUpper().startsWith("MKSM")) || // MKSM3600036 (b.name().toUpper().startsWith("YS_C1_")) || // Yesoul C1H diff --git a/src/homeform.cpp b/src/homeform.cpp index 4d142355a..6f2467987 100644 --- a/src/homeform.cpp +++ b/src/homeform.cpp @@ -551,7 +551,7 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) { deviceConnected(b); } -#ifdef Q_OS_ANDROID +#ifndef Q_OS_IOS iphone_browser = new QMdnsEngine::Browser(&iphone_server, "_qz_iphone._tcp.local.", &iphone_cache); QObject::connect(iphone_browser, &QMdnsEngine::Browser::serviceAdded, [](const QMdnsEngine::Service &service) { @@ -2870,8 +2870,8 @@ void homeform::pelotonOffset_Minus() { Minus(QStringLiteral("peloton_offset")); void homeform::bluetoothDeviceConnected(bluetoothdevice *b) { this->innerTemplateManager->start(b); this->userTemplateManager->start(b); -#ifdef Q_OS_ANDROID - // heart rate received from apple watch while QZ is running on android via TCP socket (iphone_socket) +#ifndef Q_OS_IOS + // heart rate received from apple watch while QZ is running on a different device via TCP socket (iphone_socket) connect(this, SIGNAL(heartRate(uint8_t)), b, SLOT(heartRate(uint8_t))); #endif } @@ -5064,7 +5064,7 @@ void homeform::update() { lapTrigger = false; } -#ifdef Q_OS_ANDROID +#ifndef Q_OS_IOS if (iphone_socket && iphone_socket->state() == QAbstractSocket::ConnectedState) { QString toSend = "SENDER=PAD#HR=" + QString::number(bluetoothManager->device()->currentHeart().value()) + diff --git a/src/homeform.h b/src/homeform.h index 798163b8d..ece288fd2 100644 --- a/src/homeform.h +++ b/src/homeform.h @@ -719,7 +719,9 @@ class homeform : public QObject { #ifdef Q_OS_ANDROID bool floating_open = false; +#endif +#ifndef Q_OS_IOS QMdnsEngine::Browser* iphone_browser = nullptr; QMdnsEngine::Resolver* iphone_resolver = nullptr; QMdnsEngine::Server iphone_server; diff --git a/src/main.qml b/src/main.qml index 4c25dcf63..8028565a7 100644 --- a/src/main.qml +++ b/src/main.qml @@ -745,7 +745,7 @@ ApplicationWindow { } ItemDelegate { - text: "version 2.16.13" + text: "version 2.16.15" width: parent.width } diff --git a/src/proformbike.cpp b/src/proformbike.cpp index 4013c8a31..78c44066b 100644 --- a/src/proformbike.cpp +++ b/src/proformbike.cpp @@ -1042,6 +1042,7 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte m_pelotonResistance = 30; break; case 0x0b: + case 0x0c: Resistance = 5; m_pelotonResistance = 35; break; @@ -1050,6 +1051,7 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte m_pelotonResistance = 40; break; case 0x10: + case 0x11: Resistance = 7; m_pelotonResistance = 45; break; @@ -1078,6 +1080,7 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte m_pelotonResistance = 75; break; case 0x21: + case 0x22: Resistance = 14; m_pelotonResistance = 80; break; @@ -1086,6 +1089,7 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte m_pelotonResistance = 85; break; case 0x26: + case 0x27: Resistance = 16; m_pelotonResistance = 100; break; diff --git a/src/proformrower.cpp b/src/proformrower.cpp index bbcc60baf..2c6d5613f 100644 --- a/src/proformrower.cpp +++ b/src/proformrower.cpp @@ -59,6 +59,8 @@ void proformrower::forceResistance(resistance_t requestResistance) { settings.value(QZSettings::proform_rower_sport_rl, QZSettings::default_proform_rower_sport_rl).toBool(); if (proform_rower_sport_rl) { + const uint8_t unlock_res[] = {0xfe, 0x02, 0x0d, 0x02}; + const uint8_t res1[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x14, 0x09, 0x02, 0x01, 0x04, 0x76, 0x01, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00}; const uint8_t res2[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x14, 0x09, 0x02, 0x01, @@ -108,6 +110,8 @@ void proformrower::forceResistance(resistance_t requestResistance) { const uint8_t res24[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x14, 0x09, 0x02, 0x01, 0x04, 0xe6, 0x26, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic((uint8_t*)unlock_res, sizeof(unlock_res), QStringLiteral("unlock_resistance"), false, false); + switch (requestResistance) { case 1: writeCharacteristic((uint8_t *)res1, sizeof(res1), QStringLiteral("resistance1"), false, true); @@ -325,6 +329,9 @@ void proformrower::update() { update_metrics(true, watts()); { + bool proform_rower_sport_rl = + settings.value(QZSettings::proform_rower_sport_rl, QZSettings::default_proform_rower_sport_rl).toBool(); + uint8_t noOpData1[] = {0xfe, 0x02, 0x17, 0x03}; uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x14, 0x13, 0x02, 0x00, 0x0d, 0x1c, 0x9e, 0x31, 0x00, 0x00, 0x40, 0x40, 0x00, 0x80}; @@ -347,8 +354,16 @@ void proformrower::update() { writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("noOp")); break; case 3: + if (requestResistance != -1 && proform_rower_sport_rl) { + if (requestResistance != currentResistance().value() && requestResistance >= 0 && + requestResistance <= max_resistance) { + emit debug(QStringLiteral("writing resistance ") + QString::number(requestResistance)); + forceResistance(requestResistance); + } + requestResistance = -1; + } writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp"), true); - if (requestResistance != -1) { + if (requestResistance != -1 && !proform_rower_sport_rl) { if (requestResistance != currentResistance().value() && requestResistance >= 0 && requestResistance <= max_resistance) { emit debug(QStringLiteral("writing resistance ") + QString::number(requestResistance)); @@ -414,12 +429,14 @@ double proformrower::GetResistanceFromPacket(QByteArray packet) { case 6: return 4; case 7: + case 8: return 5; case 9: return 6; case 0x0b: return 7; case 0x0c: + case 0x0d: return 8; case 0x0e: return 9; @@ -430,12 +447,14 @@ double proformrower::GetResistanceFromPacket(QByteArray packet) { case 0x13: return 12; case 0x14: + case 0x15: return 13; case 0x16: return 14; case 0x18: return 15; case 0x19: + case 0x1a: return 16; case 0x1b: return 17; @@ -452,6 +471,7 @@ double proformrower::GetResistanceFromPacket(QByteArray packet) { case 0x25: return 23; case 0x26: + case 0x27: return 24; } return 1; @@ -471,7 +491,10 @@ void proformrower::characteristicChanged(const QLowEnergyCharacteristic &charact if (newValue.length() == 20 && (uint8_t)newValue.at(0) == 0xff && newValue.at(1) == 0x11) { Cadence = (uint8_t)(newValue.at(12)); + StrokesCount += (Cadence.value()) * + ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())) / 60000; emit debug(QStringLiteral("Current Cadence: ") + QString::number(Cadence.value())); + emit debug(QStringLiteral("Strokes Count: ") + QString::number(StrokesCount.value())); uint16_t s = (((uint16_t)((uint8_t)newValue.at(14)) << 8) + (uint16_t)((uint8_t)newValue.at(13))); if (s > 0) Speed = (60.0 / (double)(s)) * 30.0; @@ -528,6 +551,9 @@ void proformrower::characteristicChanged(const QLowEnergyCharacteristic &charact } void proformrower::btinit() { + QSettings settings; + bool proform_rower_sport_rl = + settings.value(QZSettings::proform_rower_sport_rl, QZSettings::default_proform_rower_sport_rl).toBool(); { uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; @@ -545,6 +571,7 @@ void proformrower::btinit() { uint8_t initData8[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x95, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t initData9[] = {0xfe, 0x02, 0x2c, 0x04}; + uint8_t initData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x14, 0x28, 0x90, 0x07, 0x01, 0xed, 0xe8, 0xe9, 0xe8, 0xf5, 0xf0, 0x09, 0x00, 0x1d}; uint8_t initData11[] = {0x01, 0x12, 0x28, 0x39, 0x48, 0x55, 0x60, 0x99, 0xb0, 0xad, @@ -568,6 +595,13 @@ void proformrower::btinit() { uint8_t noOpData9[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x13, 0x13, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData10_proform_rower_sport_rl[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x14, 0x28, 0x90, 0x07, 0x01, 0xf2, 0xf4, 0xf4, 0xf2, 0xfe, 0x08, 0x00, 0x1e, 0x2a}; + uint8_t initData11_proform_rower_sport_rl[] = {0x01, 0x12, 0x3c, 0x4c, 0x5a, 0x66, 0x90, 0x88, 0xa6, 0xc2, 0xe4, 0x04, 0x22, 0x4e, 0x98, 0xb0, 0xce, 0x1a, 0x2c, 0x7c}; + uint8_t initData12_proform_rower_sport_rl[] = {0xff, 0x08, 0x8a, 0xd6, 0x20, 0x98, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + uint8_t noOpData7_proform_rower_sport_rl[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x14, 0x15, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData8_proform_rower_sport_rl[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); QThread::msleep(400); writeCharacteristic(initData2, sizeof(initData2), QStringLiteral("init"), false, false); @@ -594,26 +628,53 @@ void proformrower::btinit() { 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); - writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false); - QThread::msleep(400); - writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false); - QThread::msleep(400); - writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); - QThread::msleep(400); - writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("init"), false, false); - QThread::msleep(400); - writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("init"), false, false); - QThread::msleep(400); - writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); - QThread::msleep(400); - writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("init"), false, false); - QThread::msleep(400); - writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("init"), false, false); - QThread::msleep(400); - writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); - QThread::msleep(400); + if (proform_rower_sport_rl) { + writeCharacteristic(initData10_proform_rower_sport_rl, sizeof(initData10_proform_rower_sport_rl), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(initData11_proform_rower_sport_rl, sizeof(initData11_proform_rower_sport_rl), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(initData12_proform_rower_sport_rl, sizeof(initData12_proform_rower_sport_rl), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData7_proform_rower_sport_rl, sizeof(noOpData7_proform_rower_sport_rl), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData8_proform_rower_sport_rl, sizeof(noOpData8_proform_rower_sport_rl), QStringLiteral("init"), false, true); + QThread::msleep(400); + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("init"), false, false); + QThread::msleep(400); + } else { + 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(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("init"), false, false); + QThread::msleep(400); + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); + QThread::msleep(400); + } /*writeCharacteristic(noOpData7, sizeof(noOpData7), QStringLiteral("init"), false, false); QThread::msleep(400); writeCharacteristic(noOpData8, sizeof(noOpData8), QStringLiteral("init"), false, false); diff --git a/src/qdomyos-zwift.pri b/src/qdomyos-zwift.pri index 0b598f593..e250004d2 100644 --- a/src/qdomyos-zwift.pri +++ b/src/qdomyos-zwift.pri @@ -815,4 +815,4 @@ INCLUDEPATH += purchasing/inapp WINRT_MANIFEST = AppxManifest.xml -VERSION = 2.16.13 +VERSION = 2.16.15 diff --git a/src/virtualrower.cpp b/src/virtualrower.cpp index 4df88d98a..b061060d5 100644 --- a/src/virtualrower.cpp +++ b/src/virtualrower.cpp @@ -59,12 +59,13 @@ virtualrower::virtualrower(bluetoothdevice *t, bool noWriteResistance, bool noHe QLowEnergyCharacteristicData charDataFIT; charDataFIT.setUuid((QBluetoothUuid::CharacteristicType)0x2ACC); // FitnessMachineFeatureCharacteristicUuid QByteArray valueFIT; - valueFIT.append((char)0xA6); // cadence, pace and resistance level supported - valueFIT.append((char)0x45); // stride count,heart rate, power supported - valueFIT.append((char)0x00); + + valueFIT.append((char)0x83); + valueFIT.append((char)0x14); valueFIT.append((char)0x00); - valueFIT.append((char)0x0C); // resistance and power target supported valueFIT.append((char)0x00); + valueFIT.append((char)0x0C); + valueFIT.append((char)0xe0); valueFIT.append((char)0x00); valueFIT.append((char)0x00); charDataFIT.setValue(valueFIT); @@ -378,22 +379,29 @@ void virtualrower::rowerProvider() { if (!heart_only) { - value.append((char)0xA8); // resistance level, power and speed - value.append((char)0x02); // heart rate + value.append((char)0x2C); + value.append((char)0x03); value.append((char)((uint8_t)(Rower->currentCadence().value() * 2) & 0xFF)); // Stroke Rate value.append((char)((uint16_t)(((rower *)Rower)->currentStrokesCount().value()) & 0xFF)); // Stroke Count value.append((char)(((uint16_t)(((rower *)Rower)->currentStrokesCount().value()) >> 8) & 0xFF)); // Stroke Count + value.append((char)(((uint16_t)(((rower *)Rower)->odometer())) & 0xFF)); // Distance + value.append((char)(((uint16_t)(((rower *)Rower)->odometer()) >> 8) & 0xFF)); // Distance + value.append((char)(((uint16_t)(((rower *)Rower)->odometer()) >> 16) & 0xFF)); // Distance + value.append((char)(((uint16_t)QTime(0, 0, 0).secsTo(((rower *)Rower)->currentPace())) & 0xFF)); // pace value.append((char)(((uint16_t)QTime(0, 0, 0).secsTo(((rower *)Rower)->currentPace())) >> 8) & 0xFF); // pace value.append((char)(((uint16_t)Rower->wattsMetric().value()) & 0xFF)); // watts value.append((char)(((uint16_t)Rower->wattsMetric().value()) >> 8) & 0xFF); // watts - value.append((char)((uint16_t)(Rower->currentResistance().value()) & 0xFF)); // resistance - value.append((char)(((uint16_t)(Rower->currentResistance().value()) >> 8) & 0xFF)); // resistance + value.append((char)((uint16_t)(Rower->calories().value()) & 0xFF)); // calories + value.append((char)(((uint16_t)(Rower->calories().value()) >> 8) & 0xFF)); // calories + value.append((char)((uint16_t)(Rower->calories().value()) & 0xFF)); // calories + value.append((char)(((uint16_t)(Rower->calories().value()) >> 8) & 0xFF)); // calories + value.append((char)((uint16_t)(Rower->calories().value()) & 0xFF)); // calories value.append(char(Rower->currentHeart().value())); // Actual value. value.append((char)0); // Bkool FTMS protocol HRM offset 1280 fix