diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 999978c8f..bea1fde85 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -70,15 +70,20 @@ jobs: - uses: actions/setup-python@v4 with: - python-version: 3.10.11 + python-version: 3.7 - name: download python and paddleocr run: | python -VV + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools + python -m pip install "protobuf<=3.20.2,>=3.1.0" + python -m pip install paddlepaddle==2.5.1 + python -m pip install paddleocr + python -m pip install imutils + python -m pip install "Pillow<10.0.0" python -m pip install opencv-python + python -m pip install numpy python -m pip install pywin32 - python -m pip install paddlepaddle-gpu==2.4.2.post117 -f https://www.paddlepaddle.org.cn/whl/windows/mkl/avx/stable.html - python -m pip install https://files.pythonhosted.org/packages/03/ac/13fbe0ebf110d57a89f055a292d4fe430fee3fb22c56f8c077e63e0c5a4e/paddlepaddle-2.4.2-cp310-cp310-win_amd64.whl - python -m pip install paddleocr>=2.0.1 if: matrix.config.python - uses: msys2/setup-msys2@v2 @@ -117,16 +122,20 @@ jobs: make install cd ../.. + - name: Secrets + if: github.ref == 'refs/heads/main' + run: | + 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 + echo "${{ secrets.cesiumkey }}" >> inner_templates/googlemaps/cesium-key.js + cd .. + - name: Build run: | qmake - 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 - echo "${{ secrets.cesiumkey }}" >> inner_templates/googlemaps/cesium-key.js - cd .. make -j8 cd src/debug mkdir output @@ -144,7 +153,7 @@ jobs: cp ../../../windows_openssl/*.* . mkdir adb mkdir python - Copy-Item -Path C:\hostedtoolcache\windows\Python\3.10.11\x64 -Destination python -Recurse + Copy-Item -Path C:\hostedtoolcache\windows\Python\3.7.9\x64 -Destination python -Recurse cp ../../adb/* adb/ cd .. cd appx @@ -154,13 +163,6 @@ jobs: - name: Build without python run: | qmake - 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 - echo "${{ secrets.cesiumkey }}" >> inner_templates/googlemaps/cesium-key.js - cd .. make -j8 cd src/debug mkdir output @@ -528,37 +530,12 @@ jobs: sudo apt-get install -y xvfb Xvfb -ac ${{ env.DISPLAY }} -screen 0 1280x780x24 & - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 - - name: Checkout submodule repo - uses: actions/checkout@v2 - with: - repository: bluetiger9/SmtpClient-for-Qt - path: "src/smtpclient/" - ref: 3fa4a0fe5797070339422cf18b5e9ed8dcb91f9c - - - uses: actions/checkout@v2 - - name: Checkout submodule repo - uses: actions/checkout@v2 - with: - repository: cagnulein/qmdnsengine - path: "src/qmdnsengine/" - ref: "zwift" - - - uses: actions/checkout@v2 - - name: Checkout submodule repo - uses: actions/checkout@v2 - with: - repository: google/googletest - path: "tst/googletest/" - ref: "release-1.12.1" - - - uses: actions/checkout@v2 - - name: Checkout qHttpServer + - name: Checkout repository uses: actions/checkout@v2 with: - repository: qt-labs/qthttpserver - path: "src/qthttpserver" + # This token is provided by Actions, you do not need to create your own token + token: ${{ secrets.GITHUB_TOKEN }} + submodules: recursive # or 'true' if you want to check out only immediate submodules - name: Install packages required to run QZ inside workflow run: sudo apt update -y && sudo apt-get install -y qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools qtquickcontrols2-5-dev libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 libqt5networkauth5-dev libqt5websockets5* libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev @@ -646,6 +623,8 @@ jobs: ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK rm -rf /usr/local/lib/android/sdk/ndk/25.1.8937393 qmake -spec android-clang 'ANDROID_ABIS=armeabi-v7a arm64-v8a x86 x86_64' 'ANDROID_NDK_ROOT=/usr/local/lib/android/sdk/ndk/21.4.7075529' && make -j4 && make INSTALL_ROOT=${{ github.workspace }}/output/android/ install + sed -i '1s|{|{\n "android-extra-libs": "${{ github.workspace }}/android_openssl/no-asm/latest/arm/libcrypto_1_1.so,${{ github.workspace }}/android_openssl/no-asm/latest/arm/libssl_1_1.so,${{ github.workspace }}/android_openssl/no-asm/latest/arm64/libcrypto_1_1.so,${{ github.workspace }}/android_openssl/no-asm/latest/arm64/libssl_1_1.so,${{ github.workspace }}/android_openssl/no-asm/latest/x86/libcrypto_1_1.so,${{ github.workspace }}/android_openssl/no-asm/latest/x86/libssl_1_1.so,${{ github.workspace }}/android_openssl/no-asm/latest/x86_64/libcrypto_1_1.so,${{ github.workspace }}/android_openssl/no-asm/latest/x86_64/libssl_1_1.so",|' src/android-qdomyos-zwift-deployment-settings.json + cat src/android-qdomyos-zwift-deployment-settings.json - 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 @@ -786,15 +765,20 @@ jobs: - uses: actions/setup-python@v4 with: - python-version: 3.10.11 + python-version: 3.7 - name: download python and paddleocr run: | python -VV + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools + python -m pip install "protobuf<=3.20.2,>=3.1.0" + python -m pip install paddlepaddle==2.5.1 + python -m pip install paddleocr + python -m pip install imutils + python -m pip install "Pillow<10.0.0" python -m pip install opencv-python + python -m pip install numpy python -m pip install pywin32 - python -m pip install paddlepaddle-gpu==2.4.2.post117 -f https://www.paddlepaddle.org.cn/whl/windows/mkl/avx/stable.html - python -m pip install https://files.pythonhosted.org/packages/03/ac/13fbe0ebf110d57a89f055a292d4fe430fee3fb22c56f8c077e63e0c5a4e/paddlepaddle-2.4.2-cp310-cp310-win_amd64.whl - python -m pip install paddleocr>=2.0.1 if: matrix.config.python - name: Install Qt @@ -829,16 +813,20 @@ jobs: nmake install cd ../.. + - name: Secrets + if: github.ref == 'refs/heads/main' + run: | + 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 + echo "${{ secrets.cesiumkey }}" >> inner_templates/googlemaps/cesium-key.js + cd .. + - name: Build run: | - qmake - 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 - echo "${{ secrets.cesiumkey }}" >> inner_templates/googlemaps/cesium-key.js - cd .. + qmake nmake cd src/debug mkdir output @@ -853,7 +841,7 @@ jobs: cp ../../../windows_openssl/*.* . mkdir adb mkdir python - Copy-Item -Path C:\hostedtoolcache\windows\Python\3.10.11\x64 -Destination python -Recurse + Copy-Item -Path C:\hostedtoolcache\windows\Python\3.7.9\x64 -Destination python -Recurse cp ../../adb/* adb/ cd .. cd appx @@ -862,14 +850,7 @@ jobs: - name: Build without python run: | - qmake - 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 - echo "${{ secrets.cesiumkey }}" >> inner_templates/googlemaps/cesium-key.js - cd .. + qmake nmake cd src/debug mkdir output @@ -915,6 +896,121 @@ jobs: path: windows-msvc2019-binary-no-python.zip if: ${{ ! matrix.config.python }} + window-msvc2019-aiserver-build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Checkout submodule repo + uses: actions/checkout@v2 + with: + repository: bluetiger9/SmtpClient-for-Qt + path: "src/smtpclient/" + ref: 3fa4a0fe5797070339422cf18b5e9ed8dcb91f9c + + - uses: actions/checkout@v2 + - name: Checkout submodule repo + uses: actions/checkout@v2 + with: + repository: cagnulein/qmdnsengine + path: "src/qmdnsengine/" + ref: "zwift" + + - uses: actions/checkout@v2 + - name: Checkout submodule repo + uses: actions/checkout@v2 + with: + repository: google/googletest + path: "tst/googletest/" + ref: "release-1.12.1" + + - uses: actions/checkout@v2 + - name: Checkout qHttpServer + uses: actions/checkout@v2 + with: + repository: qt-labs/qthttpserver + path: "src/qthttpserver" + + - name: Install Qt + uses: jurplel/install-qt-action@v3 + with: + version: '5.15.2' + host: 'windows' + modules: 'qtnetworkauth qtcharts' + target: "desktop" + arch: win64_msvc2019_64 + dir: "${{github.workspace}}/qt/" + install-deps: "true" + cache: 'true' + cache-key-prefix: 'install-qt-action-windows' + + - name: Install MSVC compiler + uses: ilammy/msvc-dev-cmd@v1 + with: + # 14.1 is for vs2017, 14.2 is vs2019, following the upstream vcpkg build from Qv2ray-deps repo + toolset: 14.2 + arch: x64 + + - name: download 3rd party files for qthttpserver + run: | + cp qHttpServerBin/5.15.2/headers/* src/qthttpserver/src/3rdparty/http-parser/ + + - name: Build qthttpserver + run: | + cd src\qthttpserver + qmake + nmake + nmake install + cd ../.. + + - name: Secrets + if: github.ref == 'refs/heads/main' + run: | + 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 + echo "${{ secrets.cesiumkey }}" >> inner_templates/googlemaps/cesium-key.js + cd .. + + - name: Build + run: | + cd src + echo "#define AISERVER" >> aiserver.h + cd .. + qmake + nmake + cd src/debug + mkdir output + mkdir appx + cp qdomyos-zwift.exe output/ + cd output + windeployqt --qmldir ../../ qdomyos-zwift.exe + cp ../../../icons/iOS/iTunesArtwork@2x.png . + cp ../../AppxManifest.xml . + cp ../../windows/zwift-incline-ai-server.py zwift-incline.py + cp ../../windows/zwift-incline-climb-portal-ai-server.py zwift-incline-climb-portal.py + cp ../../windows/zwift-workout-ai-server.py zwift-workout.py + cp ../../windows/*.bat . + cp ../../../windows_openssl/*.* . + mkdir adb + cp ../../adb/* adb/ + cd .. + cd appx + #../../MSIX-Toolkit/WindowsSDK/10/10.0.20348.0/x64/makeappx.exe pack /d ../output/ /p qz + + - name: patching qt for bluetooth + run: cp qt-patches/windows/5.15.2/binary/msvc2019/*.* ${{ github.workspace }}/src/debug/output/ + + - name: Zip artifact for deployment + run: Compress-Archive src/debug/output windows-msvc2019-ai-server-binary.zip + + - name: Archive windows binary + uses: actions/upload-artifact@v2 + with: + name: windows-msvc2019-ai-server-binary + path: windows-msvc2019-ai-server-binary.zip + upload_to_release: permissions: write-all runs-on: ubuntu-latest @@ -944,6 +1040,7 @@ jobs: files: | windows-msvc2019-binary-no-python/* windows-msvc2019-binary/* + windows-msvc2019-ai-server-binary/* windows-binary-no-python/* windows-binary/* fdroid-android-trial/* diff --git a/.gitmodules b/.gitmodules index 4020943b6..e8d32e15c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ path = tst/googletest url = https://github.com/google/googletest.git branch = tags/release-1.12.1 +[submodule "src/qthttpserver"] + path = src/qthttpserver + url = https://github.com/qt-labs/qthttpserver diff --git a/README.md b/README.md index fb41e661d..96d3f2501 100644 --- a/README.md +++ b/README.md @@ -7,31 +7,95 @@ Zwift bridge for Treadmills and Bike! [](https://apps.apple.com/app/id1543684531?fbclid=IwAR10H6y3mEgwkTlGJON3e8voYOh2wt3kLFOpFzoIXaYZ_N0y0pDvKxHMUaM) Buy Me A Coffee -![UI](docs/img/treadmill-bridge-schema.png) - -[![Video](https://img.youtube.com/vi/GgG3dMhmo2Y/0.jpg)](https://www.youtube.com/watch?v=GgG3dMhmo2Y) - -![UI](docs/img/ui.png) -![UI](docs/img/realtime-chart.png) - -UI on Linux - -![UI](docs/img/ui-mac.png) - -UI on MacOS + + + + + + + + +
+ + + + + + + + + +
### Features -1. Domyos compatible -2. Toorx TRX Route Key compatible -3. Echelon Connect Sport compatible -4. Zwift compatible -5. Create, load and save train programs -6. Measure distance, elevation gain and watts -7. Gpx import (with difficulty slider) -8. Realtime Charts +# UI Features + +|Feature|Bike|Treadmill|Elliptical|Rower|Notes| +|:---|:---:|:---:|:---:|:---:|---:| +|Tiles Customization|X|X|X|X|Order and visibility of each tile| +|Profiles|X|X|X|X|Different user or different fitness device profiles| +|UI Zoom Customization|X|X|X|X|| + +# Peloton Features + +|Feature|Bike|Treadmill|Elliptical|Rower|Notes| +|:---|:---:|:---:|:---:|:---:|---:| +|Bike metrics on the peloton app|X||X||| +|Power zone with auto resistance|X||||| +|Peloton real-time resistance conversion|X||X||with the possibility to customize it| +|Peloton real-time auto-resistance|X||X||with the possibility to customize it| +|Peloton auto speed and auto inclination||X|X||with the possibility to customize it| + +# Heart Rate Features + +|Feature|Bike|Treadmill|Elliptical|Rower|Notes| +|:---|:---:|:---:|:---:|:---:|---:| +|Heart Rate support|X|X|X|X|Apple Watch, ANT+ devices and Bluetooth devices| +|Heart Rate Zones Customizations|X|X|X|X|| +|Ability to calculate Wattage from HR and Cadence|X||||for the bikes that doesn't have a power sensor| + +# 3rd Apps Compatibility + +|Feature|Bike|Treadmill|Elliptical|Rower|Notes| +|:---|:---:|:---:|:---:|:---:|---:| +|Zwift Compatibility|X|X|X|X|| +|Zwift Auto resistance|X||X||| +|Zwift Auto inclination and speed||X|X||https://www.youtube.com/watch?v=KTQ2n7yeDbo| +|Wahoo RGT Compatibility|X|X|X|X|| +|VzFit Compatibility|X|X|X|X|| +|Rouvy Compatibility|X|X|X|X|| +|IFIT app Compatibility|X||||| +|Echelon app Compatibility|X||||| +|Wahoo Dircon Compatibility|X|X|X|X|in order to send data to Zwift or RGT with Wifi only!| +|One device only support for Zwift and Wahoo RGT|X|X|X|X|using Wahoo Dircon https://www.youtube.com/watch?v=gYYUXNWFAok| + +# Training Program +|Feature|Bike|Treadmill|Elliptical|Rower|Notes| +|:---|:---:|:---:|:---:|:---:|---:| +|Builtin video support (Kinomap like)|X|X|X|X|Files could be local or on the cloud!| +|GPX auto following|X|X|X|X|| +|2D/3D maps for GPX|X|X|X|X|| +|ZWO (Zwift workout file) compatibility|X|X|X|X|| +|XML Workout file compatibility|X|X|X|X|| +|Auto follow workout based on your heart rate|X|X|X|X|| +|Random workout|X|X|X|X|| + + +# Statistics + +|Feature|Bike|Treadmill|Elliptical|Rower|Notes| +|:---|:---:|:---:|:---:|:---:|---:| +|E-Mail report|X|X|X|X|at the end of the workout| +|Strava integration|X|X|X|X|press stop at the end of the workout to auto upload it| + +# Misc + +|Feature|Bike|Treadmill|Elliptical|Rower|Notes| +|:---|:---:|:---:|:---:|:---:|---:| +|Resistance shifting with bluetooth remote|X||X||| +|TTS support|X|X|X|X|| -![First Success](docs/img/first_success.jpg) ### Installation diff --git a/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/qdomyoszwift-Bridging-Header.h b/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/qdomyoszwift-Bridging-Header.h index 1b2cb5d6d..11eb40c0e 100644 --- a/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/qdomyoszwift-Bridging-Header.h +++ b/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/qdomyoszwift-Bridging-Header.h @@ -2,3 +2,4 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // +#import "swiftDebug.h" 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 1fd5fa58e..4a1854031 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 @@ -170,6 +170,10 @@ 872261F0289EA887006A6F75 /* moc_nordictrackelliptical.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 872261EF289EA887006A6F75 /* moc_nordictrackelliptical.cpp */; }; 8727A47727849EA600019B5D /* paferstreadmill.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8727A47627849EA600019B5D /* paferstreadmill.cpp */; }; 8727A47927849EB200019B5D /* moc_paferstreadmill.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8727A47827849EB200019B5D /* moc_paferstreadmill.cpp */; }; + 8727C7D02B3BF1B8005429EB /* proformtelnetbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8727C7CC2B3BF1B8005429EB /* proformtelnetbike.cpp */; }; + 8727C7D12B3BF1B8005429EB /* QTelnet.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8727C7CF2B3BF1B8005429EB /* QTelnet.cpp */; }; + 8727C7D42B3BF1E4005429EB /* moc_QTelnet.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8727C7D22B3BF1E4005429EB /* moc_QTelnet.cpp */; }; + 8727C7D52B3BF1E4005429EB /* moc_proformtelnetbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8727C7D32B3BF1E4005429EB /* moc_proformtelnetbike.cpp */; }; 872A20DA28C5EC380037774D /* faketreadmill.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 872A20D928C5EC380037774D /* faketreadmill.cpp */; }; 872A20DC28C5F5CE0037774D /* moc_faketreadmill.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 872A20DB28C5F5CE0037774D /* moc_faketreadmill.cpp */; }; 872BAB4E261750EE006A59AB /* libQt5Charts.a in Link Binary With Libraries */ = {isa = PBXBuildFile; fileRef = 872BAB4D261750EE006A59AB /* libQt5Charts.a */; }; @@ -178,6 +182,11 @@ 872DCC3B2A18D4C000EC9F68 /* moc_virtualdevice.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 872DCC3A2A18D4C000EC9F68 /* moc_virtualdevice.cpp */; }; 873063BE259DF20000DA0F44 /* heartratebelt.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 873063BC259DF20000DA0F44 /* heartratebelt.cpp */; }; 873063C0259DF2C500DA0F44 /* moc_heartratebelt.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 873063BF259DF2C500DA0F44 /* moc_heartratebelt.cpp */; }; + 8730A38B2B404081007E336D /* SwiftProtobuf in Link Binary With Libraries */ = {isa = PBXBuildFile; productRef = 8730A38A2B404081007E336D /* SwiftProtobuf */; }; + 8730A38D2B404081007E336D /* SwiftProtobufPluginLibrary in Link Binary With Libraries */ = {isa = PBXBuildFile; productRef = 8730A38C2B404081007E336D /* SwiftProtobufPluginLibrary */; }; + 8730A38F2B404081007E336D /* protoc-gen-swift in Link Binary With Libraries */ = {isa = PBXBuildFile; productRef = 8730A38E2B404081007E336D /* protoc-gen-swift */; }; + 8730A3922B404159007E336D /* zwift_protobuf_layer.swift in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8730A3912B404159007E336D /* zwift_protobuf_layer.swift */; }; + 8730A3932B4078E6007E336D /* zwift_messages.pb.swift in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8730A3902B4040AF007E336D /* zwift_messages.pb.swift */; }; 87310B1E266FBB59008BA0D6 /* smartrowrower.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87310B1B266FBB54008BA0D6 /* smartrowrower.cpp */; }; 87310B1F266FBB59008BA0D6 /* homefitnessbuddy.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87310B1C266FBB57008BA0D6 /* homefitnessbuddy.cpp */; }; 87310B22266FBB78008BA0D6 /* moc_homefitnessbuddy.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87310B20266FBB6E008BA0D6 /* moc_homefitnessbuddy.cpp */; }; @@ -261,6 +270,9 @@ 874D272029AFA11F0007C079 /* apexbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 874D271E29AFA11F0007C079 /* apexbike.cpp */; }; 874D272229AFA13B0007C079 /* moc_apexbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 874D272129AFA13B0007C079 /* moc_apexbike.cpp */; }; 8752B4CD27F43D9200E2EC6C /* qz.storekit in Copy Bundle Resources */ = {isa = PBXBuildFile; fileRef = 8752B4CC27F43D9200E2EC6C /* qz.storekit */; }; + 8752C0E32B15D84100C3D1A5 /* moc_eliteariafan.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8752C0E22B15D84100C3D1A5 /* moc_eliteariafan.cpp */; }; + 8752C0E82B15D85600C3D1A5 /* eliteariafan.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8752C0E42B15D85600C3D1A5 /* eliteariafan.cpp */; }; + 8752C0E92B15D85600C3D1A5 /* ios_eliteariafan.mm in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8752C0E62B15D85600C3D1A5 /* ios_eliteariafan.mm */; }; 87540FAD2848FD70005E0D44 /* libqtexttospeech_speechios.a in Link Binary With Libraries */ = {isa = PBXBuildFile; fileRef = 87540FAC2848FD70005E0D44 /* libqtexttospeech_speechios.a */; }; 8754D24C27F786F0003D7054 /* virtualrower.swift in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8754D24B27F786F0003D7054 /* virtualrower.swift */; }; 87586A4125B8340E00A243C4 /* proformbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87586A4025B8340E00A243C4 /* proformbike.cpp */; }; @@ -322,6 +334,8 @@ 878531652711A3E1004B153D /* activiotreadmill.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 878531612711A3E1004B153D /* activiotreadmill.cpp */; }; 878531682711A3EC004B153D /* moc_activiotreadmill.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 878531662711A3EB004B153D /* moc_activiotreadmill.cpp */; }; 878531692711A3EC004B153D /* moc_fakebike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 878531672711A3EB004B153D /* moc_fakebike.cpp */; }; + 8785D5432B3DD105005A2EB7 /* moc_PlayerStateWrapper.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8785D5412B3DD105005A2EB7 /* moc_PlayerStateWrapper.cpp */; }; + 8785D5442B3DD105005A2EB7 /* moc_zwift_client_auth.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8785D5422B3DD105005A2EB7 /* moc_zwift_client_auth.cpp */; }; 878A331A25AB4FF800BD13E1 /* yesoulbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 878A331725AB4FF800BD13E1 /* yesoulbike.cpp */; }; 878A331D25AB50C300BD13E1 /* moc_yesoulbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 878A331B25AB50C200BD13E1 /* moc_yesoulbike.cpp */; }; 878C9E6928B77E7C00669129 /* nordictrackifitadbbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 878C9E6828B77E7B00669129 /* nordictrackifitadbbike.cpp */; }; @@ -364,6 +378,7 @@ 87A0D7542A3A4547005147F2 /* moc_fakerower.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87A0D7532A3A4547005147F2 /* moc_fakerower.cpp */; }; 87A18F072660D5C1002D7C96 /* ftmsrower.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87A18F052660D5C0002D7C96 /* ftmsrower.cpp */; }; 87A18F092660D5D9002D7C96 /* moc_ftmsrower.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87A18F082660D5D9002D7C96 /* moc_ftmsrower.cpp */; }; + 87A2E0222B2B053E00E6168F /* swiftDebug.mm in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87A2E0212B2B053E00E6168F /* swiftDebug.mm */; }; 87A3BC222656429600D302E3 /* rower.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87A3BC1F2656429400D302E3 /* rower.cpp */; }; 87A3BC232656429600D302E3 /* echelonrower.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87A3BC202656429400D302E3 /* echelonrower.cpp */; }; 87A3BC26265642A300D302E3 /* moc_rower.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87A3BC24265642A200D302E3 /* moc_rower.cpp */; }; @@ -883,6 +898,13 @@ 8727A47527849EA600019B5D /* paferstreadmill.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = paferstreadmill.h; path = ../src/paferstreadmill.h; sourceTree = ""; }; 8727A47627849EA600019B5D /* paferstreadmill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = paferstreadmill.cpp; path = ../src/paferstreadmill.cpp; sourceTree = ""; }; 8727A47827849EB200019B5D /* moc_paferstreadmill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_paferstreadmill.cpp; sourceTree = ""; }; + 8727C7CC2B3BF1B8005429EB /* proformtelnetbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = proformtelnetbike.cpp; path = ../src/proformtelnetbike.cpp; sourceTree = ""; }; + 8727C7CD2B3BF1B8005429EB /* proformtelnetbike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = proformtelnetbike.h; path = ../src/proformtelnetbike.h; sourceTree = ""; }; + 8727C7CE2B3BF1B8005429EB /* QTelnet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QTelnet.h; path = ../src/QTelnet.h; sourceTree = ""; }; + 8727C7CF2B3BF1B8005429EB /* QTelnet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = QTelnet.cpp; path = ../src/QTelnet.cpp; sourceTree = ""; }; + 8727C7D22B3BF1E4005429EB /* moc_QTelnet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_QTelnet.cpp; sourceTree = ""; }; + 8727C7D32B3BF1E4005429EB /* moc_proformtelnetbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_proformtelnetbike.cpp; sourceTree = ""; }; + 8729149E2B2B010600565E33 /* qdomyoszwift-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "qdomyoszwift-Bridging-Header.h"; sourceTree = ""; }; 872A20D828C5EC380037774D /* faketreadmill.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = faketreadmill.h; path = ../src/faketreadmill.h; sourceTree = ""; }; 872A20D928C5EC380037774D /* faketreadmill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = faketreadmill.cpp; path = ../src/faketreadmill.cpp; sourceTree = ""; }; 872A20DB28C5F5CE0037774D /* moc_faketreadmill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_faketreadmill.cpp; sourceTree = ""; }; @@ -894,6 +916,8 @@ 873063BC259DF20000DA0F44 /* heartratebelt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = heartratebelt.cpp; path = ../src/heartratebelt.cpp; sourceTree = ""; }; 873063BD259DF20000DA0F44 /* heartratebelt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = heartratebelt.h; path = ../src/heartratebelt.h; sourceTree = ""; }; 873063BF259DF2C500DA0F44 /* moc_heartratebelt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_heartratebelt.cpp; sourceTree = ""; }; + 8730A3902B4040AF007E336D /* zwift_messages.pb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = zwift_messages.pb.swift; path = "../src/zwift-api/zwift_messages.pb.swift"; sourceTree = ""; }; + 8730A3912B404159007E336D /* zwift_protobuf_layer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = zwift_protobuf_layer.swift; path = "../src/zwift-api/zwift_protobuf_layer.swift"; sourceTree = ""; }; 87310B1A266FBB54008BA0D6 /* homefitnessbuddy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = homefitnessbuddy.h; path = ../src/homefitnessbuddy.h; sourceTree = ""; }; 87310B1B266FBB54008BA0D6 /* smartrowrower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = smartrowrower.cpp; path = ../src/smartrowrower.cpp; sourceTree = ""; }; 87310B1C266FBB57008BA0D6 /* homefitnessbuddy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = homefitnessbuddy.cpp; path = ../src/homefitnessbuddy.cpp; sourceTree = ""; }; @@ -1018,6 +1042,11 @@ 874D271F29AFA11F0007C079 /* apexbike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = apexbike.h; path = ../src/apexbike.h; sourceTree = ""; }; 874D272129AFA13B0007C079 /* moc_apexbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_apexbike.cpp; sourceTree = ""; }; 8752B4CC27F43D9200E2EC6C /* qz.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = qz.storekit; sourceTree = ""; }; + 8752C0E22B15D84100C3D1A5 /* moc_eliteariafan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_eliteariafan.cpp; sourceTree = ""; }; + 8752C0E42B15D85600C3D1A5 /* eliteariafan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = eliteariafan.cpp; path = ../src/eliteariafan.cpp; sourceTree = ""; }; + 8752C0E52B15D85600C3D1A5 /* eliteariafan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eliteariafan.h; path = ../src/eliteariafan.h; sourceTree = ""; }; + 8752C0E62B15D85600C3D1A5 /* ios_eliteariafan.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_eliteariafan.mm; path = ../src/ios/ios_eliteariafan.mm; sourceTree = ""; }; + 8752C0E72B15D85600C3D1A5 /* ios_eliteariafan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ios_eliteariafan.h; path = ../src/ios/ios_eliteariafan.h; sourceTree = ""; }; 87540FAC2848FD70005E0D44 /* libqtexttospeech_speechios.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libqtexttospeech_speechios.a; path = ../../Qt/5.15.2/ios/plugins/texttospeech/libqtexttospeech_speechios.a; sourceTree = ""; }; 8754D24B27F786F0003D7054 /* virtualrower.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = virtualrower.swift; path = ../src/ios/virtualrower.swift; sourceTree = ""; }; 87586A3F25B8340D00A243C4 /* proformbike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = proformbike.h; path = ../src/proformbike.h; sourceTree = ""; }; @@ -1113,6 +1142,10 @@ 878531632711A3E1004B153D /* fakebike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fakebike.h; path = ../src/fakebike.h; sourceTree = ""; }; 878531662711A3EB004B153D /* moc_activiotreadmill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_activiotreadmill.cpp; sourceTree = ""; }; 878531672711A3EB004B153D /* moc_fakebike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_fakebike.cpp; sourceTree = ""; }; + 8785D53F2B3DD0EC005A2EB7 /* zwift_client_auth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zwift_client_auth.h; path = "../src/zwift-api/zwift_client_auth.h"; sourceTree = ""; }; + 8785D5402B3DD0EC005A2EB7 /* PlayerStateWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlayerStateWrapper.h; path = "../src/zwift-api/PlayerStateWrapper.h"; sourceTree = ""; }; + 8785D5412B3DD105005A2EB7 /* moc_PlayerStateWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_PlayerStateWrapper.cpp; sourceTree = ""; }; + 8785D5422B3DD105005A2EB7 /* moc_zwift_client_auth.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_zwift_client_auth.cpp; sourceTree = ""; }; 8789DCDB6A4F681A76DF3F92 /* Qt5Widgets */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = Qt5Widgets; path = "/Users/cagnulein/Qt/5.15.2/ios/lib/libQt5Widgets$(QT_LIBRARY_SUFFIX).a"; sourceTree = ""; }; 878A331725AB4FF800BD13E1 /* yesoulbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = yesoulbike.cpp; path = ../src/yesoulbike.cpp; sourceTree = ""; }; 878A331825AB4FF800BD13E1 /* yesoulbike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yesoulbike.h; path = ../src/yesoulbike.h; sourceTree = ""; }; @@ -1173,6 +1206,8 @@ 87A18F052660D5C0002D7C96 /* ftmsrower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ftmsrower.cpp; path = ../src/ftmsrower.cpp; sourceTree = ""; }; 87A18F062660D5C1002D7C96 /* ftmsrower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ftmsrower.h; path = ../src/ftmsrower.h; sourceTree = ""; }; 87A18F082660D5D9002D7C96 /* moc_ftmsrower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_ftmsrower.cpp; sourceTree = ""; }; + 87A2E0202B2B024200E6168F /* swiftDebug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = swiftDebug.h; path = ../src/ios/swiftDebug.h; sourceTree = ""; }; + 87A2E0212B2B053E00E6168F /* swiftDebug.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = swiftDebug.mm; path = ../src/ios/swiftDebug.mm; sourceTree = ""; }; 87A3BC1E2656429300D302E3 /* echelonrower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = echelonrower.h; path = ../src/echelonrower.h; sourceTree = ""; }; 87A3BC1F2656429400D302E3 /* rower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = rower.cpp; path = ../src/rower.cpp; sourceTree = ""; }; 87A3BC202656429400D302E3 /* echelonrower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = echelonrower.cpp; path = ../src/echelonrower.cpp; sourceTree = ""; }; @@ -1650,6 +1685,7 @@ 4FA524144B680D741D33EACB /* qtgraphicaleffectsprivate in Link Binary With Libraries */, 879F74152893D732009A64C8 /* CoreMedia.framework in Link Binary With Libraries */, 1C823E40F377B93A664EAC1B /* modelsplugin in Link Binary With Libraries */, + 8730A38D2B404081007E336D /* SwiftProtobufPluginLibrary in Link Binary With Libraries */, B9DED9CC16B0F3339F363FBF /* workerscriptplugin in Link Binary With Libraries */, 023642106C14651D2E1F4D5D /* dialogplugin in Link Binary With Libraries */, 133CA0345CD2BFB03079A655 /* qmlfolderlistmodelplugin in Link Binary With Libraries */, @@ -1658,6 +1694,7 @@ 3BD5A5F95DF5239184791B58 /* dialogsprivateplugin in Link Binary With Libraries */, EF98F8C34BE322582E9B73D7 /* qtquickcontrolsplugin in Link Binary With Libraries */, 7C8D236C48F2964061C3457C /* widgetsplugin in Link Binary With Libraries */, + 8730A38B2B404081007E336D /* SwiftProtobuf in Link Binary With Libraries */, 401B341C04019FFA2146E79D /* Qt5Widgets in Link Binary With Libraries */, 61EC5BE7EEC8D905C63FF628 /* qmlplugin in Link Binary With Libraries */, 877A080D2893DC4300C0F0AB /* CoreVideo.framework in Link Binary With Libraries */, @@ -1671,6 +1708,7 @@ 5A4A6C1B12D4D769431E876E /* qtquickcontrols2materialstyleplugin in Link Binary With Libraries */, A044AC393BA2327284BB63B4 /* qtquickcontrols2fusionstyleplugin in Link Binary With Libraries */, B413AFE7A08F2D63D57F683E /* qtquickcontrols2universalstyleplugin in Link Binary With Libraries */, + 8730A38F2B404081007E336D /* protoc-gen-swift in Link Binary With Libraries */, 7BA3E396471B90F086588B5C /* qtgraphicaleffectsplugin in Link Binary With Libraries */, F020E5470020A5BF3EB828A3 /* qtquickcontrols2imaginestyleplugin in Link Binary With Libraries */, 964DFEF4056724121ED9A98D /* Qt5QuickControls2 in Link Binary With Libraries */, @@ -1895,6 +1933,24 @@ 2EB56BE3C2D93CDAB0C52E67 /* Sources */ = { isa = PBXGroup; children = ( + 8730A3902B4040AF007E336D /* zwift_messages.pb.swift */, + 8785D5412B3DD105005A2EB7 /* moc_PlayerStateWrapper.cpp */, + 8785D5422B3DD105005A2EB7 /* moc_zwift_client_auth.cpp */, + 8785D5402B3DD0EC005A2EB7 /* PlayerStateWrapper.h */, + 8785D53F2B3DD0EC005A2EB7 /* zwift_client_auth.h */, + 8727C7D32B3BF1E4005429EB /* moc_proformtelnetbike.cpp */, + 8727C7D22B3BF1E4005429EB /* moc_QTelnet.cpp */, + 8727C7CC2B3BF1B8005429EB /* proformtelnetbike.cpp */, + 8727C7CD2B3BF1B8005429EB /* proformtelnetbike.h */, + 8727C7CF2B3BF1B8005429EB /* QTelnet.cpp */, + 8727C7CE2B3BF1B8005429EB /* QTelnet.h */, + 87A2E0212B2B053E00E6168F /* swiftDebug.mm */, + 8729149E2B2B010600565E33 /* qdomyoszwift-Bridging-Header.h */, + 8752C0E42B15D85600C3D1A5 /* eliteariafan.cpp */, + 8752C0E52B15D85600C3D1A5 /* eliteariafan.h */, + 8752C0E72B15D85600C3D1A5 /* ios_eliteariafan.h */, + 8752C0E62B15D85600C3D1A5 /* ios_eliteariafan.mm */, + 8752C0E22B15D84100C3D1A5 /* moc_eliteariafan.cpp */, 8745B2772AFCB52800991A39 /* AdbClient.h */, 87A0D7502A3A4517005147F2 /* fakerower.cpp */, 87A0D7512A3A4517005147F2 /* fakerower.h */, @@ -2253,6 +2309,8 @@ 35E903698E72424585D33829 /* virtualtreadmill.h */, C8CE72E7B224D8B886614E3F /* domyosbike.h */, 8710707229C4A5E70094D0F3 /* GarminConnect.swift */, + 87A2E0202B2B024200E6168F /* swiftDebug.h */, + 8730A3912B404159007E336D /* zwift_protobuf_layer.swift */, ); name = Sources; sourceTree = ""; @@ -2780,6 +2838,11 @@ 876E4E312594748100BD5714 /* PBXTargetDependency */, ); name = qdomyoszwift; + packageProductDependencies = ( + 8730A38A2B404081007E336D /* SwiftProtobuf */, + 8730A38C2B404081007E336D /* SwiftProtobufPluginLibrary */, + 8730A38E2B404081007E336D /* protoc-gen-swift */, + ); productName = qdomyoszwift; productReference = 040B10E2EF2CEF79F2205FE2 /* qdomyoszwift.app */; productType = "com.apple.product-type.application"; @@ -2855,6 +2918,9 @@ Base, ); mainGroup = E8C543AB96796ECAA2E65C57 /* qdomyoszwift */; + packageReferences = ( + 8730A3892B404081007E336D /* XCRemoteSwiftPackageReference "swift-protobuf" */, + ); productRefGroup = FE0A091FDBFB3E9C31B7A1BD /* Products */; projectDirPath = ""; projectRoot = ""; @@ -2995,15 +3061,20 @@ 87DF68BD25E2675100FCDA46 /* moc_eslinkertreadmill.cpp in Compile Sources */, 87646C2027B5064600F82131 /* bhfitnesselliptical.cpp in Compile Sources */, 8718CBAD263063CE004BF4EE /* moc_templateinfosender.cpp in Compile Sources */, + 8752C0E32B15D84100C3D1A5 /* moc_eliteariafan.cpp in Compile Sources */, + 8752C0E92B15D85600C3D1A5 /* ios_eliteariafan.mm in Compile Sources */, 87C5F0D326285E7E0067A1B5 /* moc_mimecontentformatter.cpp in Compile Sources */, 8718CBAB263063CE004BF4EE /* moc_templateinfosenderbuilder.cpp in Compile Sources */, C6B3CD471768392E18F85819 /* fit_accumulated_field.cpp in Compile Sources */, + 8730A3932B4078E6007E336D /* zwift_messages.pb.swift in Compile Sources */, 3D7395B0A17915A06361C7F3 /* fit_accumulator.cpp in Compile Sources */, 2A61806454201575EDB3F94F /* fit_buffer_encode.cpp in Compile Sources */, 87F02E4229178545000DB52C /* moc_octaneelliptical.cpp in Compile Sources */, 87E2F85D291ED308002BDC65 /* lifefitnesstreadmill.cpp in Compile Sources */, + 8752C0E82B15D85600C3D1A5 /* eliteariafan.cpp in Compile Sources */, 87917A7328E768D200F8D9AC /* Browser.swift in Compile Sources */, 873CD20B27EF8D8A000131BC /* inapptransaction.cpp in Compile Sources */, + 8727C7D52B3BF1E4005429EB /* moc_proformtelnetbike.cpp in Compile Sources */, 873824EF27E647A9004F1B46 /* query.cpp in Compile Sources */, 876F45FF279350D9003CDA5A /* moc_concept2skierg.cpp in Compile Sources */, BE93C6EF2C2A6BFEEC9EA565 /* fit_buffered_mesg_broadcaster.cpp in Compile Sources */, @@ -3031,6 +3102,7 @@ 87CC3B9D25A08812001EC5A8 /* moc_domyoselliptical.cpp in Compile Sources */, 87900DC6268B672E000CB351 /* renphobike.cpp in Compile Sources */, 879F16462847E55C00CE4945 /* proformellipticaltrainer.cpp in Compile Sources */, + 8730A3922B404159007E336D /* zwift_protobuf_layer.swift in Compile Sources */, 87917A7728E768D200F8D9AC /* Client.swift in Compile Sources */, 873824B927E64707004F1B46 /* moc_provider.cpp in Compile Sources */, 8727A47727849EA600019B5D /* paferstreadmill.cpp in Compile Sources */, @@ -3096,6 +3168,7 @@ 87097D2F275EA9A30020EE6F /* sportsplusbike.cpp in Compile Sources */, 333C629F93DB3941862924F7 /* fit_field_base.cpp in Compile Sources */, 87473A9827ECAA0500C203F5 /* moc_proformrower.cpp in Compile Sources */, + 8785D5442B3DD105005A2EB7 /* moc_zwift_client_auth.cpp in Compile Sources */, EEC10275DF646075E08DDC9B /* fit_field_definition.cpp in Compile Sources */, 87062645259480AB00D06586 /* LocalNotificationHelper.swift in Compile Sources */, 8718CBA4263063BD004BF4EE /* templateinfosenderbuilder.cpp in Compile Sources */, @@ -3137,6 +3210,7 @@ 87EB918727EE5FE7002535E1 /* moc_nautilusbike.cpp in Compile Sources */, 873824B827E64707004F1B46 /* moc_cache.cpp in Compile Sources */, 873824E427E647A8004F1B46 /* cache.cpp in Compile Sources */, + 87A2E0222B2B053E00E6168F /* swiftDebug.mm in Compile Sources */, 87310B1E266FBB59008BA0D6 /* smartrowrower.cpp in Compile Sources */, 87A3BC222656429600D302E3 /* rower.cpp in Compile Sources */, C719682D8D421AF6B2DAAEA9 /* main.cpp in Compile Sources */, @@ -3238,9 +3312,11 @@ 873824E727E647A8004F1B46 /* record.cpp in Compile Sources */, B38F3288D4AE4025465C1953 /* moc_bike.cpp in Compile Sources */, 87EFB57025BD704A0039DD5A /* moc_proformtreadmill.cpp in Compile Sources */, + 8727C7D42B3BF1E4005429EB /* moc_QTelnet.cpp in Compile Sources */, C3D1FD2587BF6F15B58BA675 /* moc_bluetooth.cpp in Compile Sources */, 87062648259480B700D06586 /* WorkoutTracking.swift in Compile Sources */, 8C3422A825EF7ECD78951307 /* moc_bluetoothdevice.cpp in Compile Sources */, + 8785D5432B3DD105005A2EB7 /* moc_PlayerStateWrapper.cpp in Compile Sources */, 1FBBC7C86C436CAAAFD37E56 /* moc_domyostreadmill.cpp in Compile Sources */, 876BFCA027BE35D8001D7645 /* moc_proformelliptical.cpp in Compile Sources */, 873824BD27E64707004F1B46 /* moc_resolver_p.cpp in Compile Sources */, @@ -3286,6 +3362,7 @@ 87D269A025F535200076AA48 /* skandikawiribike.cpp in Compile Sources */, 8738249427E646E3004F1B46 /* characteristicnotifier2a5b.cpp in Compile Sources */, 8768D1FB285081FE00F58E3A /* nordictrackifitadbtreadmill.cpp in Compile Sources */, + 8727C7D12B3BF1B8005429EB /* QTelnet.cpp in Compile Sources */, 8775008329E876F8008E48B7 /* iconceptelliptical.cpp in Compile Sources */, 87B187BD29B8C577007EEF9D /* moc_ziprotreadmill.cpp in Compile Sources */, 877FBA2B276E684E00F6C0C9 /* moc_bowflextreadmill.cpp in Compile Sources */, @@ -3317,6 +3394,7 @@ 8703BAED273C67B60058E206 /* moc_pafersbike.cpp in Compile Sources */, 873824E627E647A8004F1B46 /* hostname.cpp in Compile Sources */, 74C43649C9C4E2E5F9378019 /* moc_domyosbike.cpp in Compile Sources */, + 8727C7D02B3BF1B8005429EB /* proformtelnetbike.cpp in Compile Sources */, 87E0761D277A081A00FDA0F9 /* technogymmyruntreadmillrfcomm.cpp in Compile Sources */, 873824B327E64707004F1B46 /* moc_dirconprocessor.cpp in Compile Sources */, 87A0771229B6420200A368BF /* moc_wahookickrheadwind.cpp in Compile Sources */, @@ -3676,7 +3754,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 661; + CURRENT_PROJECT_VERSION = 705; DEVELOPMENT_TEAM = 6335M7T29D; ENABLE_BITCODE = NO; HEADER_SEARCH_PATHS = ( @@ -3829,6 +3907,7 @@ QT_LIBRARY_SUFFIX = ""; SDKROOT = iphoneos; SWIFT_INSTALL_OBJC_HEADER = YES; + SWIFT_OBJC_BRIDGING_HEADER = "qdomyoszwift-Bridging-Header.h"; SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(SWIFT_MODULE_NAME)-Swift2.h"; SWIFT_PRECOMPILE_BRIDGING_HEADER = YES; SWIFT_VERSION = 5.0; @@ -3845,7 +3924,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 661; + CURRENT_PROJECT_VERSION = 705; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 6335M7T29D; ENABLE_BITCODE = NO; @@ -4001,6 +4080,7 @@ QT_LIBRARY_SUFFIX = _debug; SDKROOT = iphoneos; SWIFT_INSTALL_OBJC_HEADER = YES; + SWIFT_OBJC_BRIDGING_HEADER = "qdomyoszwift-Bridging-Header.h"; SWIFT_OBJC_INTERFACE_HEADER_NAME = "$(SWIFT_MODULE_NAME)-Swift2.h"; SWIFT_PRECOMPILE_BRIDGING_HEADER = YES; SWIFT_VERSION = 5.0; @@ -4050,7 +4130,7 @@ CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 661; + CURRENT_PROJECT_VERSION = 705; DEVELOPMENT_TEAM = 6335M7T29D; ENABLE_BITCODE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -4146,7 +4226,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 661; + CURRENT_PROJECT_VERSION = 705; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 6335M7T29D; ENABLE_BITCODE = YES; @@ -4238,7 +4318,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 661; + CURRENT_PROJECT_VERSION = 705; DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\""; ENABLE_BITCODE = YES; ENABLE_PREVIEWS = YES; @@ -4352,7 +4432,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 661; + CURRENT_PROJECT_VERSION = 705; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\""; ENABLE_BITCODE = YES; @@ -4462,6 +4542,35 @@ defaultConfigurationName = Debug; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 8730A3892B404081007E336D /* XCRemoteSwiftPackageReference "swift-protobuf" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-protobuf.git"; + requirement = { + kind = exactVersion; + version = 1.25.2; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 8730A38A2B404081007E336D /* SwiftProtobuf */ = { + isa = XCSwiftPackageProductDependency; + package = 8730A3892B404081007E336D /* XCRemoteSwiftPackageReference "swift-protobuf" */; + productName = SwiftProtobuf; + }; + 8730A38C2B404081007E336D /* SwiftProtobufPluginLibrary */ = { + isa = XCSwiftPackageProductDependency; + package = 8730A3892B404081007E336D /* XCRemoteSwiftPackageReference "swift-protobuf" */; + productName = SwiftProtobufPluginLibrary; + }; + 8730A38E2B404081007E336D /* protoc-gen-swift */ = { + isa = XCSwiftPackageProductDependency; + package = 8730A3892B404081007E336D /* XCRemoteSwiftPackageReference "swift-protobuf" */; + productName = "protoc-gen-swift"; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 6DB9C3763D02B1415CD9D565 /* Project object */; } diff --git a/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/watchkit Extension/WatchWorkoutTracking.swift b/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/watchkit Extension/WatchWorkoutTracking.swift index 053886591..627835218 100755 --- a/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/watchkit Extension/WatchWorkoutTracking.swift +++ b/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/watchkit Extension/WatchWorkoutTracking.swift @@ -162,6 +162,12 @@ extension WorkoutTracking: WorkoutTrackingProtocol { HKSampleType.quantityType(forIdentifier: .cyclingPower)!, HKSampleType.quantityType(forIdentifier: .cyclingSpeed)!, HKSampleType.quantityType(forIdentifier: .cyclingCadence)!, + HKSampleType.quantityType(forIdentifier: .runningPower)!, + HKSampleType.quantityType(forIdentifier: .runningSpeed)!, + HKSampleType.quantityType(forIdentifier: .runningStrideLength)!, + HKSampleType.quantityType(forIdentifier: .runningVerticalOscillation)!, + HKSampleType.quantityType(forIdentifier: .walkingSpeed)!, + HKSampleType.quantityType(forIdentifier: .walkingStepLength)!, HKSampleType.workoutType() ]) } else { @@ -335,64 +341,131 @@ extension WorkoutTracking: HKLiveWorkoutBuilderDelegate { } } - if #available(watchOSApplicationExtension 10.0, *) { - let wattPerInterval = HKQuantity(unit: HKUnit.watt(), - doubleValue: WorkoutTracking.power) - - if(WorkoutTracking.lastDateMetric.distance(to: Date()) < 1) { + if(sport == 0) { + if #available(watchOSApplicationExtension 10.0, *) { + let wattPerInterval = HKQuantity(unit: HKUnit.watt(), + doubleValue: WorkoutTracking.power) + + if(WorkoutTracking.lastDateMetric.distance(to: Date()) < 1) { + return + } + + guard let powerType = HKQuantityType.quantityType( + forIdentifier: .cyclingPower) else { return - } - - guard let powerType = HKQuantityType.quantityType( - forIdentifier: .cyclingPower) else { - return - } - let wattPerIntervalSample = HKQuantitySample(type: powerType, - quantity: wattPerInterval, - start: WorkoutTracking.lastDateMetric, - end: Date()) - workoutBuilder.add([wattPerIntervalSample]) {(success, error) in - if let error = error { - print(error) } - } + let wattPerIntervalSample = HKQuantitySample(type: powerType, + quantity: wattPerInterval, + start: WorkoutTracking.lastDateMetric, + end: Date()) + workoutBuilder.add([wattPerIntervalSample]) {(success, error) in + if let error = error { + print(error) + } + } - let cadencePerInterval = HKQuantity(unit: HKUnit.count().unitDivided(by: HKUnit.second()), - doubleValue: WorkoutTracking.cadence / 60.0) - - guard let cadenceType = HKQuantityType.quantityType( - forIdentifier: .cyclingCadence) else { - return - } - let cadencePerIntervalSample = HKQuantitySample(type: cadenceType, - quantity: cadencePerInterval, - start: WorkoutTracking.lastDateMetric, - end: Date()) - workoutBuilder.add([cadencePerIntervalSample]) {(success, error) in - if let error = error { - print(error) + let cadencePerInterval = HKQuantity(unit: HKUnit.count().unitDivided(by: HKUnit.second()), + doubleValue: WorkoutTracking.cadence / 60.0) + + guard let cadenceType = HKQuantityType.quantityType( + forIdentifier: .cyclingCadence) else { + return + } + let cadencePerIntervalSample = HKQuantitySample(type: cadenceType, + quantity: cadencePerInterval, + start: WorkoutTracking.lastDateMetric, + end: Date()) + workoutBuilder.add([cadencePerIntervalSample]) {(success, error) in + if let error = error { + print(error) + } } + + let speedPerInterval = HKQuantity(unit: HKUnit.meter().unitDivided(by: HKUnit.second()), + doubleValue: WorkoutTracking.speed * 0.277778) + + guard let speedType = HKQuantityType.quantityType( + forIdentifier: .cyclingSpeed) else { + return + } + let speedPerIntervalSample = HKQuantitySample(type: speedType, + quantity: speedPerInterval, + start: WorkoutTracking.lastDateMetric, + end: Date()) + workoutBuilder.add([speedPerIntervalSample]) {(success, error) in + if let error = error { + print(error) + } + } + + } else { + // Fallback on earlier versions } + } else if(sport == 1) { + if #available(watchOSApplicationExtension 10.0, *) { + let wattPerInterval = HKQuantity(unit: HKUnit.watt(), + doubleValue: WorkoutTracking.power) + + if(WorkoutTracking.lastDateMetric.distance(to: Date()) < 1) { + return + } + + guard let powerType = HKQuantityType.quantityType( + forIdentifier: .runningPower) else { + return + } + let wattPerIntervalSample = HKQuantitySample(type: powerType, + quantity: wattPerInterval, + start: WorkoutTracking.lastDateMetric, + end: Date()) + workoutBuilder.add([wattPerIntervalSample]) {(success, error) in + if let error = error { + print(error) + } + } - let speedPerInterval = HKQuantity(unit: HKUnit.meter().unitDivided(by: HKUnit.second()), - doubleValue: WorkoutTracking.speed * 0.277778) - - guard let speedType = HKQuantityType.quantityType( - forIdentifier: .cyclingSpeed) else { - return - } - let speedPerIntervalSample = HKQuantitySample(type: speedType, - quantity: speedPerInterval, - start: WorkoutTracking.lastDateMetric, - end: Date()) - workoutBuilder.add([speedPerIntervalSample]) {(success, error) in - if let error = error { - print(error) + let speedPerInterval = HKQuantity(unit: HKUnit.meter().unitDivided(by: HKUnit.second()), + doubleValue: WorkoutTracking.speed * 0.277778) + + guard let speedType = HKQuantityType.quantityType( + forIdentifier: .runningSpeed) else { + return } + let speedPerIntervalSample = HKQuantitySample(type: speedType, + quantity: speedPerInterval, + start: WorkoutTracking.lastDateMetric, + end: Date()) + workoutBuilder.add([speedPerIntervalSample]) {(success, error) in + if let error = error { + print(error) + } + } + + } else { + // Fallback on earlier versions } + } else if(sport == 2) { + if #available(watchOSApplicationExtension 10.0, *) { + let speedPerInterval = HKQuantity(unit: HKUnit.meter().unitDivided(by: HKUnit.second()), + doubleValue: WorkoutTracking.speed * 0.277778) + + guard let speedType = HKQuantityType.quantityType( + forIdentifier: .walkingSpeed) else { + return + } + let speedPerIntervalSample = HKQuantitySample(type: speedType, + quantity: speedPerInterval, + start: WorkoutTracking.lastDateMetric, + end: Date()) + workoutBuilder.add([speedPerIntervalSample]) {(success, error) in + if let error = error { + print(error) + } + } - } else { - // Fallback on earlier versions + } else { + // Fallback on earlier versions + } } WorkoutTracking.lastDateMetric = Date() diff --git a/src/GPXList.qml b/src/GPXList.qml index 9f0e62ff7..c3fe5eeb9 100644 --- a/src/GPXList.qml +++ b/src/GPXList.qml @@ -11,6 +11,7 @@ import QtLocation 5.6 ColumnLayout { signal trainprogram_open_clicked(url name) + signal trainprogram_open_other_folder(url name) signal trainprogram_preview(url name) FileDialog { id: fileDialogTrainProgram @@ -18,7 +19,11 @@ ColumnLayout { folder: shortcuts.home onAccepted: { console.log("You chose: " + fileDialogTrainProgram.fileUrl) - trainprogram_open_clicked(fileDialogTrainProgram.fileUrl) + if(OS_VERSION === "Android") { + trainprogram_open_other_folder(fileDialogTrainProgram.fileUrl) + } else { + trainprogram_open_clicked(fileDialogTrainProgram.fileUrl) + } fileDialogTrainProgram.close() } onRejected: { diff --git a/src/QTelnet.cpp b/src/QTelnet.cpp new file mode 100644 index 000000000..e148d2733 --- /dev/null +++ b/src/QTelnet.cpp @@ -0,0 +1,522 @@ +#include "QTelnet.h" + +#include "QTelnet.h" +#include + +const char QTelnet::IACWILL[2] = { IAC, WILL }; +const char QTelnet::IACWONT[2] = { IAC, WONT }; +const char QTelnet::IACDO[2] = { IAC, DO }; +const char QTelnet::IACDONT[2] = { IAC, DONT }; +const char QTelnet::IACSB[2] = { IAC, SB }; +const char QTelnet::IACSE[2] = { IAC, SE }; + +char QTelnet::_sendCodeArray[2] = { IAC, 0 }; +char QTelnet::_arrCRLF[2] = { 13, 10 }; +char QTelnet::_arrCR[2] = { 13, 0 }; + +QTelnet::QTelnet(QObject *parent) : + QTcpSocket(parent), m_actualSB(0) +{ + connect( this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)) ); + connect( this, SIGNAL(readyRead()), this, SLOT(onReadyRead()) ); +} + +QString QTelnet::peerInfo() const +{ + return QString("%1 (%2):%3").arg(peerName()).arg(peerAddress().toString()).arg(peerPort()); +} + +bool QTelnet::isConnected() const +{ + return state() == QAbstractSocket::ConnectedState; +} + +bool QTelnet::testBinaryMode() const +{ + return m_receivedDX[(unsigned char)TELOPT_BINARY] == DO; +} + +void QTelnet::connectToHost(const QString &host, quint16 port) +{ + if( !isConnected() ) + { + resetProtocol(); + abort(); + QTcpSocket::connectToHost(host, port); + } +} + +void QTelnet::sendData(const QByteArray &ba) +{ + if( isConnected() ) + transpose( ba.constData(), ba.count() ); +} + +void QTelnet::socketError(QAbstractSocket::SocketError err) +{ + Q_UNUSED(err); + disconnectFromHost(); +} + +void QTelnet::write(const char c) +{ + QTcpSocket::write( (char*)&c, 1 ); +} + +void QTelnet::setCustomCR(char cr, char cr2) +{ + _arrCR[0] = cr; + _arrCR[1] = cr2; +} + +void QTelnet::setCustomCRLF(char lf, char cr) +{ + _arrCR[0] = lf; + _arrCR[1] = cr; +} + +// Envia el codigo de control al servidor. +void QTelnet::sendTelnetControl(char codigo) +{ + _sendCodeArray[1] = codigo; + QTcpSocket::write(_sendCodeArray, 2); +} + +void QTelnet::writeCustomCRLF() +{ + QTcpSocket::write(_arrCRLF, 2); +} + +void QTelnet::writeCustomCR() +{ + QTcpSocket::write(_arrCR, 2); +} + +/// Resetea los datos del protocolo. Debe llamarse cada vez que se inicia una conexión nueva. +void QTelnet::resetProtocol() +{ + for( int i = 0; i < 256; i++ ) + { + m_receivedDX[i] = + m_receivedWX[i] = + m_sentDX[i] = + m_sentWX[i] = 0; + m_negotiationState = STATE_DATA; + m_buffSB.clear(); + m_actualSB = 0; + } + m_oldWinSize.setHeight(-1); + m_oldWinSize.setWidth(-1); +} + +void QTelnet::sendSB(char code, char *arr, int iLen) +{ + write(IAC); + write(SB); + write(code); + + QTcpSocket::write(arr, iLen); + + write(IAC); + write(SE); +} +void QTelnet::sendWindowSize() +{ + if( isConnected() && (m_receivedDX[TELOPT_NAWS] == DO) && (m_oldWinSize != m_winSize) ) + { + char size[4]; + + m_oldWinSize = m_winSize; + size[0] = (m_winSize.width()>>8) & 0xFF; + size[1] = m_winSize.width() & 0xFF; + size[2] = (m_winSize.height()>>8) & 0xFF; + size[3] = m_winSize.height() & 0xFF; + sendSB(TELOPT_NAWS, size, 4); + } +} + +// Handle an incoming IAC SB type chars IAC SE +void QTelnet::handleSB() +{ + switch( m_actualSB ) + { + case TELOPT_TTYPE: + if( (m_buffSB.count() > 0) && ((unsigned char)m_buffSB[0] == (unsigned char)TELQUAL_SEND) ) + { + QTcpSocket::write(IACSB, 2); + write(TELOPT_TTYPE); + write(TELQUAL_IS); + /* FIXME: need more logic here if we use + * more than one terminal type + */ + QTcpSocket::write("SiraggaTerminal", 15); + QTcpSocket::write(IACSE, 2); + } + break; + } +} + +// Analiza el texto saliente para que cumpla las normas del protocolo. +// Además ya lo escribe en el socket. +void QTelnet::transpose(const char *buf, int iLen) +{ + for( int i = 0; i < iLen; i++ ) + { + switch( buf[i] ) + { + case IAC: + // Escape IAC twice in stream ... to be telnet protocol compliant + // this is there in binary and non-binary mode. + write(IAC); + write(IAC); + break; + case 10: // \n + // We need to heed RFC 854. LF (\n) is 10, CR (\r) is 13 + // we assume that the Terminal sends \n for lf+cr and \r for just cr + // linefeed+carriage return is CR LF + + // En modo binario no se traduce nada. + if( testBinaryMode() ) + write(buf[i]); + else + writeCustomCRLF(); + break; + case 13: // \r + // carriage return is CR NUL */ + + // En modo binario no se traduce nada. + if( testBinaryMode() ) + write(buf[i]); + else + writeCustomCR(); + break; + default: + // all other characters are just copied + write(buf[i]); + break; + } + } +} + +void QTelnet::willsReply(char action, char reply) +{ + if( (reply != m_sentDX[(unsigned char)action]) || (WILL != m_receivedWX[(unsigned char)action]) ) + { + write(IAC); + write(reply); + write(action); + + m_sentDX[(unsigned char)action] = reply; + m_receivedWX[(unsigned char)action] = WILL; + } +} + +void QTelnet::wontsReply(char action, char reply) +{ + if( (reply != m_sentDX[(unsigned char)action]) || (WONT != m_receivedWX[(unsigned char)action]) ) + { + write(IAC); + write(reply); + write(action); + + m_sentDX[(unsigned char)action] = reply; + m_receivedWX[(unsigned char)action] = WONT; + } +} + +void QTelnet::doesReply(char action, char reply) +{ + if( (reply != m_sentWX[(unsigned char)action]) || (DO != m_receivedDX[(unsigned char)action]) ) + { + write(IAC); + write(reply); + write(action); + + m_sentWX[(unsigned char)action] = reply; + m_receivedDX[(unsigned char)action] = DO; + } +} + +void QTelnet::dontsReply(char action, char reply) +{ + if( (reply != m_sentWX[(unsigned char)action]) || (DONT != m_receivedDX[(unsigned char)action]) ) + { + write(IAC); + write(reply); + write(action); + + m_sentWX[(unsigned char)action] = reply; + m_receivedDX[(unsigned char)action] = DONT; + } +} + +// Analiza el buffer de entrada colocá ndolo en el buffer de procesado usando el protocolo telnet. +qint64 QTelnet::doTelnetInProtocol(qint64 buffSize) +{ + qint64 iIn, iOut; + char b; + + for( iIn = 0, iOut = 0; iIn < buffSize; iIn++ ) + { + b = m_buffIncoming[iIn]; + + switch( m_negotiationState ) + { + case STATE_DATA: + switch( b ) + { + case IAC: + m_negotiationState = STATE_IAC; + break; + case '\r': + m_negotiationState = STATE_DATAR; + break; + case '\n': + m_negotiationState = STATE_DATAN; + break; + default: + m_buffProcessed[iOut++] = b; + break; + } + break; + case STATE_DATAN: + case STATE_DATAR: + switch( b ) + { + case IAC: + m_negotiationState = STATE_IAC; + break; + case '\r': + case '\n': + m_buffProcessed[iOut++] = '\n'; + m_negotiationState = STATE_DATA; + break; + default: + m_buffProcessed[iOut++] = b; + m_negotiationState = STATE_DATA; + break; + } + break; + case STATE_IAC: + switch( b ) + { + case IAC: // Dos IAC seguidos, se intenta enviar un caracter con el valor IAC. + m_negotiationState = STATE_DATA; + m_buffProcessed[iOut++] = IAC; + break; + case WILL: + m_negotiationState = STATE_IACWILL; + break; + case WONT: + m_negotiationState = STATE_IACWONT; + break; + case DONT: + m_negotiationState = STATE_IACDONT; + break; + case DO: + m_negotiationState = STATE_IACDO; + break; + case EOR: + emitEndOfRecord(); + m_negotiationState = STATE_DATA; + break; + case SB: + m_negotiationState = STATE_IACSB; + m_buffSB.clear(); + break; + default: + m_negotiationState = STATE_DATA; + break; + } + break; + case STATE_IACWILL: + switch( b ) + { + case TELOPT_ECHO: + emitEchoLocal(false); + willsReply(b, DO); + break; + case TELOPT_SGA: + willsReply(b, DO); + break; + case TELOPT_EOR: + willsReply(b, DO); + break; + case TELOPT_BINARY: + willsReply(b, DO); + break; + default: + willsReply(b, DONT); + break; + } + m_negotiationState = STATE_DATA; + break; + case STATE_IACWONT: + switch(b) + { + case TELOPT_ECHO: + emitEchoLocal(true); + wontsReply(b, DONT); + break; + case TELOPT_SGA: + wontsReply(b, DONT); + break; + case TELOPT_EOR: + wontsReply(b, DONT); + break; + case TELOPT_BINARY: + wontsReply(b, DONT); + break; + default: + wontsReply(b, DONT); + break; + } + m_negotiationState = STATE_DATA; + break; + case STATE_IACDO: + switch( b ) + { + case TELOPT_ECHO: + doesReply(b, WILL); + emitEchoLocal(true); + break; + case TELOPT_SGA: + doesReply(b, WILL); + break; + case TELOPT_TTYPE: + doesReply(b, WILL); + break; + case TELOPT_BINARY: + doesReply(b, WILL); + break; + case TELOPT_NAWS: + m_receivedDX[(unsigned char)b] = (unsigned char)DO; + m_sentWX[(unsigned char)b] = (unsigned char)WILL; + write(IAC); + write(WILL); + write(b); + + // Enviamos el tamaño de la pantalla. + sendWindowSize(); + break; + default: + doesReply(b, WONT); + break; + } + m_negotiationState = STATE_DATA; + break; + case STATE_IACDONT: + switch (b) + { + case TELOPT_ECHO: + dontsReply(b, WONT); + emitEchoLocal(false); + break; + case TELOPT_SGA: + dontsReply(b, WONT); + break; + case TELOPT_NAWS: + dontsReply(b, WONT); + break; + case TELOPT_BINARY: + dontsReply(b, WONT); + break; + default: + dontsReply(b, WONT); + break; + } + m_negotiationState = STATE_DATA; + break; + case STATE_IACSB: + switch( b ) + { + case IAC: + // Entramos en estado IAC en la sub-negociación. + m_negotiationState = STATE_IACSBIAC; + break; + default: + // Iniciamos la sub-negociación. + m_buffSB.clear(); + m_actualSB = b; + m_negotiationState = STATE_IACSBDATA; + break; + } + break; + case STATE_IACSBDATA: // Estamos en datos de la subnegociación. + switch( b ) + { + case IAC: + m_negotiationState = STATE_IACSBDATAIAC; + break; + default: + m_buffSB.append(b); + break; + } + break; + case STATE_IACSBIAC: + switch( b ) + { + case IAC: + // Reiniciamos la sub-negociación. + m_buffSB.clear(); + m_actualSB = b; + m_negotiationState = STATE_IACSBDATA; + default: + // Salimos de la sub-negociación. + m_negotiationState = STATE_DATA; + } + break; + case STATE_IACSBDATAIAC: + switch( b ) + { + case IAC: + m_negotiationState = STATE_IACSBDATA; + m_buffSB.append(IAC); + break; + case SE: + handleSB(); + m_actualSB = 0; + m_buffSB.clear(); + m_negotiationState = STATE_DATA; + break; + case SB: + handleSB(); + m_buffSB.clear(); + m_negotiationState = STATE_IACSB; + break; + default: + m_buffSB.clear(); + m_actualSB = 0; + m_negotiationState = STATE_DATA; + break; + } + break; + default: + m_negotiationState = STATE_DATA; + break; + } + } + return iOut; +} + +void QTelnet::onReadyRead() +{ + qint64 readed; + qint64 processed; + + while( (readed = read(m_buffIncoming, IncommingBufferSize)) != 0 ) + { + switch( readed ) + { + case -1: + disconnectFromHost(); + break; + default: + processed = doTelnetInProtocol(readed); + if( processed > 0 ) + Q_EMIT(newData(m_buffProcessed, processed)); + + break; + } + } +} diff --git a/src/QTelnet.h b/src/QTelnet.h new file mode 100644 index 000000000..0807a8081 --- /dev/null +++ b/src/QTelnet.h @@ -0,0 +1,136 @@ +#ifndef QTELNET_H +#define QTELNET_H + +#include +#include +#include +#include + +#define IncommingBufferSize (1500) + +class QTelnet : public QTcpSocket +{ +Q_OBJECT + +public: + enum SocketStatus + { + Disconnected, + Resolving, // Resolving host + Connecting, // Connecting to host. + Connected // Connected to host. + }; + +protected: + enum TelnetStateCodes + { + STATE_DATA = (char)0, + STATE_IAC = (char)1, + STATE_IACSB = (char)2, + STATE_IACWILL = (char)3, + STATE_IACDO = (char)4, + STATE_IACWONT = (char)5, + STATE_IACDONT = (char)6, + STATE_IACSBIAC = (char)7, + STATE_IACSBDATA = (char)8, + STATE_IACSBDATAIAC = (char)9, + STATE_DATAR = (char)10, + STATE_DATAN = (char)11 + }; + enum TelnetCodes + { + // Negociación entrada/salida (cliente<->servidor) + IAC = (char)255, // Inicia la secuencia para la negociación telnet. + EOR = (char)239, // Estando en la negociación, End Of Record. + WILL = (char)251, // Estando en la negociación, Acepta el protocolo? + WONT = (char)252, // Estando en la negociación, Acepta el protocolo? + DO = (char)253, // Estando en la negociación, Protocolo aceptado. + DONT = (char)254, // Estando en la negociación, Protocolo denegado. + SB = (char)250, // Estando en la negociación, inicia secuencia de sub-negociación. + SE = (char)240, // Estando en la sub-negociación, fin de sub-negociación. + + // Negociación de salida (cliente->servidor) + TELOPT_BINARY = (char)0, // Estando en la negociación, pide modo binario. + TELOPT_ECHO = (char)1, // Estando en la negociación, pide echo local. + TELOPT_SGA = (char)2, // Estando en la negociación, pide Supress Go Ahead. + TELOPT_EOR = (char)25, // Estando en la negociación, informa End Of Record. + TELOPT_NAWS = (char)31, // Estando en la negociación, Negotiate Abaut Window Size. + TELOPT_TTYPE = (char)24 // Estando en la negociación, Terminal Type. + }; + enum TelnetQualifiers + { + TELQUAL_IS = (char)0, + TELQUAL_SEND = (char)1 + }; + +private: + static const char IACWILL[2]; + static const char IACWONT[2]; + static const char IACDO[2]; + static const char IACDONT[2]; + static const char IACSB[2]; + static const char IACSE[2]; + static char _sendCodeArray[2]; + static char _arrCRLF[2]; + static char _arrCR[2]; + + QSize m_winSize; // Tamaño de la pantalla en caracteres. + QSize m_oldWinSize; // Tamaño de la pantalla que se envió por última vez al server. Para no enviar el mismo dato. + enum TelnetStateCodes m_negotiationState; + char m_receivedDX[256]; // What IAC DO(NT) request do we have received already ? + char m_receivedWX[256]; // What IAC WILL/WONT request do we have received already ? + char m_sentDX[256]; // What IAC DO/DONT request do we have sent already ? + char m_sentWX[256]; // What IAC WILL/WONT request do we have sent already ? + void resetProtocol(); + + char m_buffIncoming[IncommingBufferSize]; + char m_buffProcessed[IncommingBufferSize]; + QByteArray m_buffSB; + int m_actualSB; + + void emitEndOfRecord() { Q_EMIT(endOfRecord()); } + void emitEchoLocal(bool bEcho) { Q_EMIT(echoLocal(bEcho)); } + + void sendTelnetControl(char codigo); + void handleSB(void); + void transpose(const char *buf, int iLen); + + void willsReply(char action, char reply); + void wontsReply(char action, char reply); + void doesReply(char action, char reply); + void dontsReply(char action, char reply); + + void sendSB(char code, char *arr, int iLen); + qint64 doTelnetInProtocol(qint64 buffSize); + +public: + explicit QTelnet(QObject *parent = 0); + + virtual void connectToHost(const QString &host, quint16 port); + void sendData(const QByteArray &ba); + void setCustomCRLF(char lf = 13, char cr = 10); + void setCustomCR(char cr = 10, char cr2 = 0); + + void writeCustomCRLF(); + void writeCustomCR(); + + void write(const char c); + + bool isConnected() const; + bool testBinaryMode() const; + void setWindSize(QSize s) {m_winSize = s;} + void sendWindowSize(); + + QString peerInfo()const; + +signals: + void newData(const char *buff, int len); + void endOfRecord(); + void echoLocal(bool echo); + +private slots: + void socketError(QAbstractSocket::SocketError err); + void onReadyRead(); +}; + +#endif // QTELNET_H diff --git a/src/TrainingProgramsList.qml b/src/TrainingProgramsList.qml index 5e49e71d4..cb91bb053 100644 --- a/src/TrainingProgramsList.qml +++ b/src/TrainingProgramsList.qml @@ -9,6 +9,7 @@ import Qt.labs.settings 1.0 ColumnLayout { signal trainprogram_open_clicked(url name) + signal trainprogram_open_other_folder(url name) signal trainprogram_preview(url name) FileDialog { id: fileDialogTrainProgram @@ -16,7 +17,11 @@ ColumnLayout { folder: shortcuts.home onAccepted: { console.log("You chose: " + fileDialogTrainProgram.fileUrl) - trainprogram_open_clicked(fileDialogTrainProgram.fileUrl) + if(OS_VERSION === "Android") { + trainprogram_open_other_folder(fileDialogTrainProgram.fileUrl) + } else { + trainprogram_open_clicked(fileDialogTrainProgram.fileUrl) + } fileDialogTrainProgram.close() } onRejected: { diff --git a/src/activiotreadmill.cpp b/src/activiotreadmill.cpp index 7f823d760..5eb399b98 100644 --- a/src/activiotreadmill.cpp +++ b/src/activiotreadmill.cpp @@ -297,6 +297,7 @@ void activiotreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha settings.value(QZSettings::heart_rate_belt_name, QZSettings::default_heart_rate_belt_name).toString(); Q_UNUSED(characteristic); QByteArray value = newValue; + QDateTime now = QDateTime::currentDateTime(); emit debug(QStringLiteral(" << ") + QString::number(value.length()) + QStringLiteral(" ") + value.toHex(' ')); emit packetReceived(); @@ -339,12 +340,12 @@ void activiotreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastTimeCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 Distance += ((speed / (double)3600.0) / - ((double)1000.0 / (double)(lastTimeCharacteristicChanged.msecsTo(QDateTime::currentDateTime())))); - lastTimeCharacteristicChanged = QDateTime::currentDateTime(); + ((double)1000.0 / (double)(lastTimeCharacteristicChanged.msecsTo(now)))); + lastTimeCharacteristicChanged = now; } emit debug(QStringLiteral("Current speed: ") + QString::number(speed)); diff --git a/src/android/AndroidManifest.xml b/src/android/AndroidManifest.xml index 0d5dbd1a5..779cdeaa6 100644 --- a/src/android/AndroidManifest.xml +++ b/src/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/src/android/build.gradle b/src/android/build.gradle index 842589948..3148f8fa1 100644 --- a/src/android/build.gradle +++ b/src/android/build.gradle @@ -6,9 +6,14 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.6.0' + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.4' } } +plugins { + id "com.google.protobuf" version "0.9.4" +} + repositories { google() jcenter() @@ -17,14 +22,16 @@ repositories { } apply plugin: 'com.android.application' +apply plugin: 'com.google.protobuf' def amazon = System.getenv('AMAZON') println(amazon) dependencies { compile 'com.rvalerio:fgchecker:1.1.0' - implementation "androidx.core:core-ktx:+" + implementation "androidx.core:core-ktx:1.12.0" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0" + implementation 'com.google.protobuf:protobuf-javalite:3.25.1' if(amazon == "1") { // amazon app store @@ -49,6 +56,26 @@ dependencies { implementation 'com.google.android.gms:play-services-wearable:+' } +import org.apache.tools.ant.taskdefs.condition.Os + +// Compatible with macOS on Apple Silicon +def archSuffix = Os.isFamily(Os.FAMILY_MAC) ? ':osx-x86_64' : '' + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:3.25.1$archSuffix" + } + generateProtoTasks { + all().configureEach { task -> + task.builtins { + java { + option "lite" + } + } + } + } +} + android { /******************************************************* * The following variables: diff --git a/src/android/gradle.properties b/src/android/gradle.properties index 646c51b97..094148595 100644 --- a/src/android/gradle.properties +++ b/src/android/gradle.properties @@ -1,2 +1,3 @@ android.useAndroidX=true android.enableJetifier=true +protoc_platform=osx-x86_64 diff --git a/src/android/gradlew b/src/android/gradlew old mode 100644 new mode 100755 diff --git a/src/android/src/ContentHelper.java b/src/android/src/ContentHelper.java new file mode 100644 index 000000000..4baa23697 --- /dev/null +++ b/src/android/src/ContentHelper.java @@ -0,0 +1,28 @@ +package org.cagnulen.qdomyoszwift; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.provider.OpenableColumns; +import android.util.Log; + +public class ContentHelper { + + public static String getFileName(Context context, Uri uri) { + String result = null; + if (uri.getScheme().equals("content")) { + Log.d("ContentHelper", "content"); + Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); + Log.d("ContentHelper", "cursor " + cursor); + try { + if (cursor != null && cursor.moveToFirst()) { + result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + Log.d("ContentHelper", "result " + result); + } + } finally { + cursor.close(); + } + } + return result; + } +} diff --git a/src/android/src/ZwiftAPI.java b/src/android/src/ZwiftAPI.java new file mode 100644 index 000000000..0815423c6 --- /dev/null +++ b/src/android/src/ZwiftAPI.java @@ -0,0 +1,65 @@ +package org.cagnulen.qdomyoszwift; + +import android.app.ActivityManager; +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.provider.Settings; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; +import android.os.Looper; +import android.os.Handler; +import android.util.Log; +import com.garmin.android.connectiq.ConnectIQ; +import com.garmin.android.connectiq.ConnectIQAdbStrategy; +import com.garmin.android.connectiq.IQApp; +import com.garmin.android.connectiq.IQDevice; +import com.garmin.android.connectiq.exception.InvalidStateException; +import com.garmin.android.connectiq.exception.ServiceUnavailableException; +import android.content.BroadcastReceiver; +import android.content.ContextWrapper; +import android.content.IntentFilter; +import android.widget.Toast; + +import org.jetbrains.annotations.Nullable; + +import com.google.protobuf.InvalidProtocolBufferException; + +import java.util.HashMap; +import java.util.List; + +public class ZwiftAPI { + + private static Context context; + + private static final String TAG = "ZwiftAPI: "; + private static ZwiftMessages.PlayerState playerState; + + public static void zwift_api_decodemessage_player(byte[] value) { + try { + playerState = ZwiftMessages.PlayerState.parseFrom(value); + // Ora puoi usare 'message' come un oggetto normale + } catch (InvalidProtocolBufferException e) { + // Gestisci l'eccezione se il messaggio non può essere parsato + Log.e(TAG, e.toString()); + } + } + + public static float getAltitude() { + Log.d(TAG, "getAltitude " + playerState.getAltitude()); + return playerState.getAltitude(); + } + + public static float getDistance() { + Log.d(TAG, "getDistance " + playerState.getDistance()); + return playerState.getDistance(); + } +} diff --git a/src/android/src/main/proto/zwift_messages.proto b/src/android/src/main/proto/zwift_messages.proto new file mode 100644 index 000000000..d7bc0d2b1 --- /dev/null +++ b/src/android/src/main/proto/zwift_messages.proto @@ -0,0 +1,155 @@ +syntax="proto3"; + +package org.cagnulen.qdomyoszwift; + +message PlayerState { + int32 id = 1; + int64 worldTime = 2; + int32 distance = 3; + int32 roadTime = 4; + int32 laps = 5; + int32 speed = 6; + int32 roadPosition = 8; + int32 cadenceUHz = 9; + int32 heartrate = 11; + int32 power = 12; + int64 heading = 13; + int32 lean = 14; + int32 climbing = 15; + int32 time = 16; + int32 f19 = 19; + int32 f20 = 20; + int32 progress = 21; + int64 customisationId = 22; + int32 justWatching = 23; + int32 calories = 24; + float x = 25; + float altitude = 26; + float y = 27; + int32 watchingRiderId = 28; + int32 groupId = 29; + int64 sport = 31; +} + +message ClientToServer { + int32 connected = 1; + int32 rider_id = 2; + int64 world_time = 3; + PlayerState state = 7; + int32 seqno = 4; + int64 tag8 = 8; + int64 tag9 = 9; + int64 last_update = 10; + int64 tag11 = 11; + int64 last_player_update = 12; +} + +message SegmentResult { + int64 id = 1; + int64 rider_id = 2; + int64 event_subgroup_id = 6; + string first_name = 7; + string last_name = 8; + string finish_time_str = 10; + int64 elapsed_ms = 11; + int32 powermeter = 12; + int32 weight = 13; + int32 power = 15; + int32 heartrate = 19; +} + +message SegmentResults { + int64 world_id = 1; + int64 segment_id = 2; + int64 event_subgroup_id = 3; + repeated SegmentResult segment_results = 4; +} + +message UnknownMessage1 { + // string firstName=7; + // string lastName=8; + // string timestamp=17; +} + +message UnknownMessage { + // int64 tag1=1; + // UnknownMessage1 tag4=4; +} + +message ServerToClient { + int32 tag1 = 1; + int32 rider_id = 2; + int64 world_time = 3; + int32 seqno = 4; + repeated PlayerState player_states = 8; + repeated UnknownMessage player_updates = 9; + int64 tag11 = 11; + int64 tag17 = 17; + int32 num_msgs = 18; + int32 msgnum = 19; +} + +message WorldAttributes { + int32 world_id = 1; + string name = 2; + int64 tag3 = 3; + int64 tag5 = 4; + int64 world_time = 6; + int64 clock_time = 7; +} + +message WorldAttribute { + int64 world_time = 2; +} + +message EventSubgroupProtobuf { + int32 id = 1; + string name = 2; + int32 rules = 8; + int32 route = 22; + int32 laps = 25; + int32 startLocation = 29; + int32 label = 30; + int32 paceType = 31; + int32 jerseyHash = 36; +} + +message RiderAttributes { + int32 f2 = 2; + int32 f3 = 3; + message AttributeMessage { + int32 myId = 1; + int32 theirId = 2; + string firstName = 3; + string lastName = 4; + int32 countryCode = 5; + } + AttributeMessage attributeMessage = 4; + int32 theirId = 10; + int32 f13 = 13; +} + +message Profiles { + repeated Profile profiles = 1; +} + +message Profile { + int32 id = 1; + string firstName = 4; + string lastName = 5; + int32 male = 6; + int32 weight = 9; + int32 bodyType = 12; + int32 countryCode = 34; + int32 totalDistance = 35; + int32 totalDistanceClimbed = 36; + int32 totalTimeInMinutes = 37; + int32 totalWattHours = 41; + int32 height = 42; + int32 totalExperiencePoints = 46; + int32 achievementLevel = 49; + int32 powerSource = 52; + int32 age = 55; + string launchedGameClient = 108; + int32 currentActivityId = 109; +} diff --git a/src/apexbike.cpp b/src/apexbike.cpp index 98a753a9d..b1fdbb384 100644 --- a/src/apexbike.cpp +++ b/src/apexbike.cpp @@ -129,6 +129,7 @@ void apexbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void apexbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -159,7 +160,7 @@ void apexbike::characteristicChanged(const QLowEnergyCharacteristic &characteris } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } if (watts()) KCal += @@ -167,17 +168,17 @@ void apexbike::characteristicChanged(const QLowEnergyCharacteristic &characteris settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (Cadence.value() > 0) { CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) { diff --git a/src/bhfitnesselliptical.cpp b/src/bhfitnesselliptical.cpp index 69775ca87..984651bfe 100644 --- a/src/bhfitnesselliptical.cpp +++ b/src/bhfitnesselliptical.cpp @@ -142,6 +142,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic & settings.value(QZSettings::heart_ignore_builtin, QZSettings::default_heart_ignore_builtin).toBool(); emit debug(QStringLiteral(" << ") + newValue.toHex(' ')); + QDateTime now = QDateTime::currentDateTime(); if (characteristic.uuid() == QBluetoothUuid::HeartRate && newValue.length() > 1) { Heart = (uint8_t)newValue[1]; @@ -191,7 +192,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic & } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), 0 /* not useful for elliptical*/); } index += 2; @@ -241,7 +242,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic & index += 3; } else { Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); } emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); @@ -288,7 +289,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic & settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -301,7 +302,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic & #endif { if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) { - Heart = ((double)((newValue.at(index)))); + Heart = ((double)(((uint8_t)newValue.at(index)))); // index += 1; // NOTE: clang-analyzer-deadcode.DeadStores emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); } else { @@ -326,7 +327,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic & LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (heartRateBeltName.startsWith(QStringLiteral("Disabled")) && (!Flags.heartRate || Heart.value() == 0 || disable_hr_frommachinery)) { diff --git a/src/bike.cpp b/src/bike.cpp index 4c7a85c13..995e84641 100644 --- a/src/bike.cpp +++ b/src/bike.cpp @@ -116,6 +116,7 @@ void bike::clearStats() { Speed.clear(false); KCal.clear(true); Distance.clear(true); + Distance1s.clear(true); Heart.clear(false); m_jouls.clear(true); elevationAcc = 0; @@ -140,6 +141,7 @@ void bike::setPaused(bool p) { Speed.setPaused(p); KCal.setPaused(p); Distance.setPaused(p); + Distance1s.setPaused(p); Heart.setPaused(p); m_jouls.setPaused(p); m_watt.setPaused(p); @@ -161,6 +163,7 @@ void bike::setLap() { Speed.setLap(false); KCal.setLap(true); Distance.setLap(true); + Distance1s.setLap(true); Heart.setLap(false); m_jouls.setLap(true); m_watt.setLap(false); diff --git a/src/bkoolbike.cpp b/src/bkoolbike.cpp index da6b4e3af..9e9c91017 100644 --- a/src/bkoolbike.cpp +++ b/src/bkoolbike.cpp @@ -192,6 +192,7 @@ void bkoolbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -253,8 +254,8 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri if (cadence >= 0 && cadence < 255) { Cadence = cadence; } - lastGoodCadence = QDateTime::currentDateTime(); - } else if (lastGoodCadence.msecsTo(QDateTime::currentDateTime()) > 2000) { + lastGoodCadence = now; + } else if (lastGoodCadence.msecsTo(now) > 2000) { Cadence = 0; } @@ -266,7 +267,7 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri .toDouble(); Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); // Resistance = ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | // (uint16_t)((uint8_t)newValue.at(index)))); debug("Current Resistance: " + @@ -301,9 +302,9 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; emit debug(QStringLiteral("Current CrankRevsRead: ") + QString::number(CrankRevsRead)); emit debug(QStringLiteral("Last CrankEventTime: ") + QString::number(LastCrankEventTime)); @@ -384,8 +385,8 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri if (cadence >= 0) { Cadence = cadence; } - lastGoodCadence = QDateTime::currentDateTime(); - } else if (lastGoodCadence.msecsTo(QDateTime::currentDateTime()) > 2000) { + lastGoodCadence = now; + } else if (lastGoodCadence.msecsTo(now) > 2000) { Cadence = 0; } } @@ -403,12 +404,12 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); // if we change this, also change the wattsFromResistance function. We can create a standard function in @@ -456,7 +457,7 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight + now)))); //(( (0.048* Output in watts +1.19) * body weight // in kg * 3.5) / 200 ) / 60 emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); } diff --git a/src/bluetooth.cpp b/src/bluetooth.cpp index c7e114e44..e6f48de43 100644 --- a/src/bluetooth.cpp +++ b/src/bluetooth.cpp @@ -399,6 +399,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { settings.value(QZSettings::fakedevice_treadmill, QZSettings::default_fakedevice_treadmill).toBool(); bool pafers_treadmill = settings.value(QZSettings::pafers_treadmill, QZSettings::default_pafers_treadmill).toBool(); QString proformtdf4ip = settings.value(QZSettings::proformtdf4ip, QZSettings::default_proformtdf4ip).toString(); + QString proformtdf1ip = settings.value(QZSettings::proformtdf1ip, QZSettings::default_proformtdf1ip).toString(); QString proformtreadmillip = settings.value(QZSettings::proformtreadmillip, QZSettings::default_proformtreadmillip).toString(); QString nordictrack_2950_ip = @@ -426,6 +427,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { QString ftms_bike = settings.value(QZSettings::ftms_bike, QZSettings::default_ftms_bike).toString(); QString ftms_treadmill = settings.value(QZSettings::ftms_treadmill, QZSettings::default_ftms_treadmill).toString(); bool saris_trainer = settings.value(QZSettings::saris_trainer, QZSettings::default_saris_trainer).toBool(); + bool iconsole_elliptical = settings.value(QZSettings::iconsole_elliptical, QZSettings::default_iconsole_elliptical).toBool(); if (!heartRateBeltFound) { @@ -546,6 +548,14 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { qDebug() << device.deviceUuid(); #endif + // not required for mobile I guess +#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) + if(!homeformLoaded) { + qDebug() << "homeform not yet loaded"; + return; + } +#endif + if (onlyDiscover) return; @@ -655,6 +665,21 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { emit searchingStop(); } this->signalBluetoothDeviceConnected(proformWifiBike); + } else if (!proformtdf1ip.isEmpty() && !proformTelnetBike) { + this->stopDiscovery(); + proformTelnetBike = + new proformtelnetbike(noWriteResistance, noHeartService, bikeResistanceOffset, bikeResistanceGain); + emit deviceConnected(b); + connect(proformTelnetBike, &bluetoothdevice::connectedAndDiscovered, this, + &bluetooth::connectedAndDiscovered); + // connect(cscBike, SIGNAL(disconnected()), this, SLOT(restart())); + connect(proformTelnetBike, &proformtelnetbike::debug, this, &bluetooth::debug); + proformTelnetBike->deviceDiscovered(b); + // connect(this, SIGNAL(searchingStop()), cscBike, SLOT(searchingStop())); //NOTE: Commented due to #358 + if (this->discoveryAgent && !this->discoveryAgent->isActive()) { + emit searchingStop(); + } + this->signalBluetoothDeviceConnected(proformTelnetBike); #ifndef Q_OS_IOS } else if (!computrainerSerialPort.isEmpty() && !computrainerBike) { this->stopDiscovery(); @@ -824,7 +849,8 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { emit searchingStop(); } this->signalBluetoothDeviceConnected(domyosElliptical); - } else if (b.name().toUpper().startsWith(QStringLiteral("YPOO-U3-")) && !ypooElliptical && filter) { + } else if ((b.name().toUpper().startsWith(QStringLiteral("YPOO-U3-")) || + (b.name().startsWith(QStringLiteral("FS-")) && iconsole_elliptical)) && !ypooElliptical && filter) { this->setLastBluetoothDevice(b); this->stopDiscovery(); ypooElliptical = @@ -1004,7 +1030,9 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { b.name().toUpper().startsWith(QStringLiteral("KS-HDSC-X21C")) || b.name().toUpper().startsWith(QStringLiteral("KS-HDSY-X21C")) || b.name().toUpper().startsWith(QStringLiteral("KS-NACH-X21C")) || - b.name().toUpper().startsWith(QStringLiteral("KS-NGCH-X21C"))) && + b.name().toUpper().startsWith(QStringLiteral("KS-NGCH-X21C")) || + // KingSmith Walking Pad G1 + b.name().toUpper().startsWith(QStringLiteral("KS-NGCH-G1C"))) && !kingsmithR2Treadmill && filter) { this->setLastBluetoothDevice(b); this->stopDiscovery(); @@ -1029,6 +1057,8 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { b.name().toUpper().startsWith(QStringLiteral("KINGSMITH")) || b.name().toUpper().startsWith(QStringLiteral("DYNAMAX")) || b.name().toUpper().startsWith(QStringLiteral("WALKINGPAD")) || + // Poland-distributed WalkingPad R2 TRR2FB + b.name().toUpper().startsWith(QStringLiteral("KS-SC-BLR2C")) || !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 @@ -1057,7 +1087,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { if (this->discoveryAgent && !this->discoveryAgent->isActive()) emit searchingStop(); this->signalBluetoothDeviceConnected(kingsmithR1ProTreadmill); - } else if ((b.name().toUpper().startsWith(QStringLiteral("ZW-"))) && !shuaA5Treadmill && filter) { + } else if ((b.name().toUpper().startsWith(QStringLiteral("ZW-"))) && !shuaA5Treadmill && ftms_bike.contains(QZSettings::default_ftms_bike) && filter) { this->setLastBluetoothDevice(b); this->stopDiscovery(); shuaA5Treadmill = new shuaa5treadmill(noWriteResistance, noHeartService); @@ -1175,11 +1205,13 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { !toorx_ftms && toorx_ftms_treadmill) || !b.name().compare(ftms_treadmill, Qt::CaseInsensitive) || b.name().toUpper().startsWith(QStringLiteral("MOBVOI TM")) || // FTMS + b.name().toUpper().startsWith(QStringLiteral("TUNTURI T60-")) || // FTMS b.name().toUpper().startsWith(QStringLiteral("KETTLER TREADMILL")) || // FTMS b.name().toUpper().startsWith(QStringLiteral("ASSAULTRUNNER")) || // FTMS (b.name().toUpper().startsWith(QStringLiteral("CTM")) && b.name().length() >= 15) || // FTMS (b.name().toUpper().startsWith(QStringLiteral("F85")) && !sole_inclination) || // FMTS (b.name().toUpper().startsWith(QStringLiteral("F80")) && !sole_inclination) || // FMTS + (b.name().toUpper().startsWith(QStringLiteral("ANPLUS-"))) || // FTMS b.name().toUpper().startsWith(QStringLiteral("ESANGLINKER"))) && !horizonTreadmill && filter) { this->setLastBluetoothDevice(b); @@ -1322,6 +1354,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { (b.name().toUpper().startsWith("FLXCY-")) || // Pro FlexBike (b.name().toUpper().startsWith("QB-WC01")) || // Nexgim QB-C01 smart bike (b.name().toUpper().startsWith("XBR55")) || // Sprint XBR555 + (b.name().toUpper().startsWith("ECHO_BIKE_")) || // Rogue echo bike V3.0 (b.name().toUpper().startsWith("EW-JS-")) || // EW-JS-4990 (b.name().toUpper().startsWith("DT-") && b.name().length() >= 14) || // SOLE SB700 (b.name().toUpper().startsWith("URSB") && b.name().length() == 7) || // URSB005 @@ -1330,10 +1363,11 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { settings.value(QZSettings::ss2k_peloton, QZSettings::default_ss2k_peloton) .toBool()) || // ss2k on a peloton bike (b.name().toUpper().startsWith("KICKR CORE")) || + (b.name().toUpper().startsWith("DS60-")) || (b.name().toUpper().startsWith("ZUMO")) || (b.name().toUpper().startsWith("XS08-")) || (b.name().toUpper().startsWith("B94")) || (b.name().toUpper().startsWith("STAGES BIKE")) || (b.name().toUpper().startsWith("SUITO")) || (b.name().toUpper().startsWith("D2RIDE")) || - (b.name().toUpper().startsWith("DIRETO XR")) || + (b.name().toUpper().startsWith("DIRETO XR")) || (b.name().toUpper().startsWith("MERACH-667-")) || !b.name().compare(ftms_bike, Qt::CaseInsensitive) || (b.name().toUpper().startsWith("SMB1")) || (b.name().toUpper().startsWith("UBIKE FTMS")) || (b.name().toUpper().startsWith("INRIDE"))) && !ftmsBike && !snodeBike && !fitPlusBike && !stagesBike && filter) { @@ -1377,6 +1411,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { horizonGr7Bike->deviceDiscovered(b); this->signalBluetoothDeviceConnected(horizonGr7Bike); } else if ((b.name().toUpper().startsWith(QStringLiteral("STAGES ")) || + (b.name().toUpper().startsWith(QStringLiteral("QD")) && b.name().length() == 2) || (b.name().toUpper().startsWith(QStringLiteral("ASSIOMA")) && powerSensorName.startsWith(QStringLiteral("Disabled")))) && !stagesBike && !ftmsBike && filter) { @@ -1783,7 +1818,8 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { // SLOT(inclinationChanged(double))); mcfBike->deviceDiscovered(b); this->signalBluetoothDeviceConnected(mcfBike); - } else if ((b.name().startsWith(QStringLiteral("TRX ROUTE KEY"))) && !toorx && filter) { + } else if ((b.name().startsWith(QStringLiteral("TRX ROUTE KEY")) || + b.name().toUpper().startsWith(QStringLiteral("BH-TR-"))) && !toorx && filter) { this->setLastBluetoothDevice(b); this->stopDiscovery(); toorx = new toorxtreadmill(); @@ -1868,6 +1904,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { this->signalBluetoothDeviceConnected(trxappgateusb); } else if ((b.name().toUpper().startsWith(QStringLiteral("TUN ")) || b.name().toUpper().startsWith(QStringLiteral("FITHIWAY")) || + b.name().toUpper().startsWith(QStringLiteral("FIT HI WAY")) || ((b.name().startsWith(QStringLiteral("TOORX")) || b.name().toUpper().startsWith(QStringLiteral("I-CONSOIE+")) || b.name().toUpper().startsWith(QStringLiteral("I-CONSOLE+")) || @@ -1991,13 +2028,13 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) { // connect(fitPlusBike, SIGNAL(debug(QString)), this, SLOT(debug(QString))); fitPlusBike->deviceDiscovered(b); this->signalBluetoothDeviceConnected(fitPlusBike); - } else if (((b.name().startsWith(QStringLiteral("FS-")) && !snode_bike && !fitplus_bike && !ftmsBike) || + } else if (((b.name().startsWith(QStringLiteral("FS-")) && !horizonTreadmill && !snode_bike && !fitplus_bike && !ftmsBike && !iconsole_elliptical) || b.name().toUpper().startsWith(QStringLiteral("NOBLEPRO CONNECT")) || // FTMS (b.name().startsWith(QStringLiteral("SW")) && b.name().length() == 14 && !b.name().contains('(') && !b.name().contains(')')) || (b.name().toUpper().startsWith(QStringLiteral("WINFITA"))) || // also FTMS (b.name().startsWith(QStringLiteral("BF70")))) && - !fitshowTreadmill && filter) { + !fitshowTreadmill && !iconsole_elliptical && filter) { this->setLastBluetoothDevice(b); this->stopDiscovery(); fitshowTreadmill = new fitshowtreadmill(this->pollDeviceTime, noConsole, noHeartService); @@ -2207,6 +2244,16 @@ void bluetooth::connectedAndDiscovered() { f->deviceDiscovered(b); wahookickrHeadWind.append(f); break; + } else if (((b.name().toUpper().startsWith("ARIA")) && b.name().length() == 4) && !fitmetria_fanfit_isconnected(b.name())) { + eliteariafan *f = new eliteariafan(this->device()); + + connect(f, &eliteariafan::debug, this, &bluetooth::debug); + + connect(this->device(), SIGNAL(fanSpeedChanged(uint8_t)), f, SLOT(fanSpeedRequest(uint8_t))); + + f->deviceDiscovered(b); + eliteAriaFan.append(f); + break; } } } @@ -2533,6 +2580,11 @@ void bluetooth::restart() { delete proformWifiBike; proformWifiBike = nullptr; } + if (proformTelnetBike) { + + delete proformTelnetBike; + proformTelnetBike = nullptr; + } if (proformWifiTreadmill) { delete proformWifiTreadmill; @@ -2879,6 +2931,14 @@ void bluetooth::restart() { } wahookickrHeadWind.clear(); } + if (eliteAriaFan.length()) { + + foreach (eliteariafan *f, eliteAriaFan) { + delete f; + f = nullptr; + } + eliteAriaFan.clear(); + } if (cadenceSensor) { // heartRateBelt->disconnectBluetooth(); // to test @@ -2938,6 +2998,8 @@ bluetoothdevice *bluetooth::device() { return cscBike; } else if (proformWifiBike) { return proformWifiBike; + } else if (proformTelnetBike) { + return proformTelnetBike; } else if (proformWifiTreadmill) { return proformWifiTreadmill; } else if (nordictrackifitadbTreadmill) { @@ -3207,6 +3269,10 @@ bool bluetooth::fitmetria_fanfit_isconnected(QString name) { if (!name.compare(f->bluetoothDevice.name())) return true; } + foreach (eliteariafan *f, eliteAriaFan) { + if (!name.compare(f->bluetoothDevice.name())) + return true; + } return false; } diff --git a/src/bluetooth.h b/src/bluetooth.h index 751d7fa49..2767f142d 100644 --- a/src/bluetooth.h +++ b/src/bluetooth.h @@ -41,6 +41,7 @@ #include "echelonconnectsport.h" #include "echelonrower.h" +#include "eliteariafan.h" #include "eliterizer.h" #include "elitesterzosmart.h" #include "eslinkertreadmill.h" @@ -85,6 +86,7 @@ #include "proformellipticaltrainer.h" #include "proformrower.h" #include "proformtreadmill.h" +#include "proformtelnetbike.h" #include "proformwifibike.h" #include "proformwifitreadmill.h" #include "schwinn170bike.h" @@ -145,6 +147,7 @@ class bluetooth : public QObject, public SignalHandler { bluetoothdevice *heartRateDevice() { return heartRateBelt; } QList devices; bool onlyDiscover = false; + volatile bool homeformLoaded = false; private: bool useDiscovery = false; @@ -186,6 +189,7 @@ class bluetooth : public QObject, public SignalHandler { pelotonbike *pelotonBike = nullptr; proformrower *proformRower = nullptr; proformbike *proformBike = nullptr; + proformtelnetbike *proformTelnetBike = nullptr; proformwifibike *proformWifiBike = nullptr; proformwifitreadmill *proformWifiTreadmill = nullptr; proformelliptical *proformElliptical = nullptr; @@ -250,6 +254,7 @@ class bluetooth : public QObject, public SignalHandler { faketreadmill *fakeTreadmill = nullptr; QList fitmetriaFanfit; QList wahookickrHeadWind; + QList eliteAriaFan; QString filterDevice = QLatin1String(""); bool testResistance = false; diff --git a/src/bluetoothdevice.cpp b/src/bluetoothdevice.cpp index 1f331654e..53fd9da37 100644 --- a/src/bluetoothdevice.cpp +++ b/src/bluetoothdevice.cpp @@ -267,6 +267,7 @@ void bluetoothdevice::clearStats() { Speed.clear(false); KCal.clear(true); Distance.clear(true); + Distance1s.clear(true); Heart.clear(false); m_jouls.clear(true); elevationAcc = 0; @@ -284,6 +285,7 @@ void bluetoothdevice::setPaused(bool p) { Speed.setPaused(p); KCal.setPaused(p); Distance.setPaused(p); + Distance1s.setPaused(p); Heart.setPaused(p); m_jouls.setPaused(p); m_watt.setPaused(p); @@ -299,6 +301,7 @@ void bluetoothdevice::setLap() { Speed.setLap(false); KCal.setLap(true); Distance.setLap(true); + Distance1s.setLap(true); Heart.setLap(false); m_jouls.setLap(true); m_watt.setLap(false); diff --git a/src/bluetoothdevice.h b/src/bluetoothdevice.h index b10e72dcc..3335cd262 100644 --- a/src/bluetoothdevice.h +++ b/src/bluetoothdevice.h @@ -100,6 +100,9 @@ class bluetoothdevice : public QObject { * @return */ virtual double odometer(); + virtual metric currentDistance() {return Distance;} + virtual metric currentDistance1s() {return Distance1s;} + void addCurrentDistance1s(double distance) { Distance1s += distance; } /** * @brief calories Gets a metric object to get and set the amount of energy expended. @@ -495,6 +498,7 @@ class bluetoothdevice : public QObject { * the length of belt traversed on a treadmill. */ metric Distance; + metric Distance1s; // used to populate the distance on the FIT file. Since Strava is using the distance to graph it, it has to have 1s trigger. /** * @brief FanSpeed The currently requested fan speed. Units: revolutions per second diff --git a/src/bowflext216treadmill.cpp b/src/bowflext216treadmill.cpp index bb48fca3d..21db4b99e 100644 --- a/src/bowflext216treadmill.cpp +++ b/src/bowflext216treadmill.cpp @@ -393,8 +393,14 @@ void bowflext216treadmill::serviceScanDone(void) { QBluetoothUuid _gattCommunicationChannelServiceId(QStringLiteral("15B7BF49-1693-481E-B877-69D33CE6BAFA")); gattCommunicationChannelService = m_control->createServiceObject(_gattCommunicationChannelServiceId); if (gattCommunicationChannelService == nullptr) { - qDebug() << "WRONG SERVICE"; - return; + qDebug() << "trying with the BOWFLEX BTX116 treadmill"; + bowflex_btx116 = true; + QBluetoothUuid _gattCommunicationChannelServiceId(QStringLiteral("b5c78780-cad7-11e5-b9f8-0002a5d5c51b")); + gattCommunicationChannelService = m_control->createServiceObject(_gattCommunicationChannelServiceId); + if (gattCommunicationChannelService == nullptr) { + qDebug() << "WRONG SERVICE"; + return; + } } } } diff --git a/src/bowflext216treadmill.h b/src/bowflext216treadmill.h index e407d3074..e85fe127e 100644 --- a/src/bowflext216treadmill.h +++ b/src/bowflext216treadmill.h @@ -74,6 +74,7 @@ class bowflext216treadmill : public treadmill { bool initRequest = false; bool bowflex_t6 = false; + bool bowflex_btx116 = false; Q_SIGNALS: void disconnected(); diff --git a/src/characteristicnotifier2a63.cpp b/src/characteristicnotifier2a63.cpp index 7f7a06343..dd8e3119e 100644 --- a/src/characteristicnotifier2a63.cpp +++ b/src/characteristicnotifier2a63.cpp @@ -9,10 +9,57 @@ int CharacteristicNotifier2A63::notify(QByteArray &value) { normalizeWattage = 0; if (Bike->deviceType() == bluetoothdevice::BIKE) { - value.append((char)0x20); // crank data present + /* + // set measurement + measurement[2] = power & 0xFF; + measurement[3] = (power >> 8) & 0xFF; + + measurement[4] = wheelrev & 0xFF; + measurement[5] = (wheelrev >> 8) & 0xFF; + measurement[6] = (wheelrev >> 16) & 0xFF; + measurement[7] = (wheelrev >> 24) & 0xFF; + + measurement[8] = lastwheel & 0xFF; + measurement[9] = (lastwheel >> 8) & 0xFF; + + measurement[10] = crankrev & 0xFF; + measurement[11] = (crankrev >> 8) & 0xFF; + + measurement[12] = lastcrank & 0xFF; + measurement[13] = (lastcrank >> 8) & 0xFF; + + // speed & distance + // NOTE : based on Apple Watch default wheel dimension 700c x 2.5mm + // NOTE : 3 is theoretical crank:wheel gear ratio + // NOTE : 2.13 is circumference of 700c in meters + + wheelCount = crankCount * 3; + speed = cadence * 3 * 2.13 * 60 / 1000; + distance = wheelCount * 2.13 / 1000; + + #if defined(USEPOWER) + lastWheelK = lastCrankK * 2; // 1/2048 s granularity + #else + lastWheelK = lastCrankK * 1; // 1/1024 s granularity + #endif + + */ + + uint32_t wheelCount = (uint32_t)Bike->currentCrankRevolutions() * 3; + uint16_t lastWheelK = Bike->lastCrankEventTime() * 2; + + value.append((char)0x30); // crank data present and wheel for apple watch value.append((char)0x00); value.append((char)(((uint16_t)normalizeWattage) & 0xFF)); // watt value.append((char)(((uint16_t)normalizeWattage) >> 8) & 0xFF); // watt + + value.append((char)(((uint32_t)wheelCount) & 0xFF)); // revs count + value.append((char)(((uint32_t)wheelCount) >> 8) & 0xFF); // revs count + value.append((char)(((uint32_t)wheelCount) >> 16) & 0xFF); // revs count + value.append((char)(((uint32_t)wheelCount) >> 24) & 0xFF); // revs count + value.append((char)(lastWheelK & 0xff)); // eventtime + value.append((char)(lastWheelK >> 8) & 0xFF); // eventtime + value.append((char)(((uint16_t)Bike->currentCrankRevolutions()) & 0xFF)); // revs count value.append((char)(((uint16_t)Bike->currentCrankRevolutions()) >> 8) & 0xFF); // revs count value.append((char)(Bike->lastCrankEventTime() & 0xff)); // eventtime diff --git a/src/characteristicnotifier2acc.cpp b/src/characteristicnotifier2acc.cpp index 643362aff..e58e97ce2 100644 --- a/src/characteristicnotifier2acc.cpp +++ b/src/characteristicnotifier2acc.cpp @@ -10,7 +10,7 @@ int CharacteristicNotifier2ACC::notify(QByteArray &value) { value.append((char)0x14); // heart rate and elapsed time value.append((char)0x00); value.append((char)0x00); - value.append((char)0x0C); // resistance and power target supported + value.append((char)0x0F); // resistance, power, speed and inclination target supported value.append((char)0xE0); // indoor simulation, wheel and spin down supported value.append((char)0x00); value.append((char)0x00); diff --git a/src/characteristicnotifier2acd.cpp b/src/characteristicnotifier2acd.cpp index f3849a78c..2a2b0ba95 100644 --- a/src/characteristicnotifier2acd.cpp +++ b/src/characteristicnotifier2acd.cpp @@ -8,7 +8,7 @@ CharacteristicNotifier2ACD::CharacteristicNotifier2ACD(bluetoothdevice *Bike, QO int CharacteristicNotifier2ACD::notify(QByteArray &value) { bluetoothdevice::BLUETOOTH_TYPE dt = Bike->deviceType(); if (dt == bluetoothdevice::TREADMILL || dt == bluetoothdevice::ELLIPTICAL) { - value.append(0x08); // Inclination available + value.append(0x0C); // Inclination available and distance for peloton value.append((char)0x01); // heart rate available uint16_t normalizeSpeed = (uint16_t)qRound(Bike->currentSpeed().value() * 100); @@ -17,6 +17,17 @@ int CharacteristicNotifier2ACD::notify(QByteArray &value) { QByteArray speedBytes; speedBytes.append(b); speedBytes.append(a); + + uint16_t normalizeDistance = (uint16_t)qRound(Bike->odometer() * 1000); + a = (normalizeDistance >> 16) & 0XFF; + b = (normalizeDistance >> 8) & 0XFF; + char c = normalizeDistance & 0XFF; + QByteArray distanceBytes; + distanceBytes.append(c); + distanceBytes.append(b); + distanceBytes.append(a); + + uint16_t normalizeIncline = 0; if (dt == bluetoothdevice::TREADMILL) normalizeIncline = (uint32_t)qRound(((treadmill *)Bike)->currentInclination().value() * 10); @@ -36,6 +47,8 @@ int CharacteristicNotifier2ACD::notify(QByteArray &value) { rampBytes.append(a); value.append(speedBytes); // Actual value. + + value.append(distanceBytes); // Actual value. value.append(inclineBytes); // incline diff --git a/src/chronobike.cpp b/src/chronobike.cpp index c93c7016e..03f7fad15 100644 --- a/src/chronobike.cpp +++ b/src/chronobike.cpp @@ -126,6 +126,7 @@ void chronobike::serviceDiscovered(const QBluetoothUuid &gatt) { } void chronobike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -153,7 +154,7 @@ void chronobike::characteristicChanged(const QLowEnergyCharacteristic &character } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } if (watts()) KCal += @@ -161,10 +162,10 @@ void chronobike::characteristicChanged(const QLowEnergyCharacteristic &character settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); double ac = 0.01243107769; double bc = 1.145964912; @@ -190,7 +191,7 @@ void chronobike::characteristicChanged(const QLowEnergyCharacteristic &character LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) diff --git a/src/concept2skierg.cpp b/src/concept2skierg.cpp index 18097260c..c3665578f 100644 --- a/src/concept2skierg.cpp +++ b/src/concept2skierg.cpp @@ -131,6 +131,7 @@ void concept2skierg::serviceDiscovered(const QBluetoothUuid &gatt) { } void concept2skierg::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); @@ -172,7 +173,7 @@ void concept2skierg::characteristicChanged(const QLowEnergyCharacteristic &chara break; case 0x32: qDebug() << "32"; - if (newValue.length() >= 20) { + if (newValue.length() >= 19) { // 0.001 m/s uint16_t speed_ms = (((uint16_t)((uint16_t)newValue.at(5)) << 8) | (uint16_t)((uint8_t)newValue.at(4))); uint8_t stroke_rate = newValue.at(6); @@ -238,7 +239,7 @@ void concept2skierg::characteristicChanged(const QLowEnergyCharacteristic &chara LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) { update_hr_from_external(); diff --git a/src/cscbike.cpp b/src/cscbike.cpp index 55f3ed0ab..a47aa6c0f 100644 --- a/src/cscbike.cpp +++ b/src/cscbike.cpp @@ -138,6 +138,7 @@ void cscbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -211,8 +212,8 @@ void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characterist double cadence = ((CrankRevs - oldCrankRevs) / deltaT) * 1024 * 60; if (cadence >= 0 && cadence < 256) Cadence = cadence; - lastGoodCadence = QDateTime::currentDateTime(); - } else if (lastGoodCadence.msecsTo(QDateTime::currentDateTime()) > 2000) { + lastGoodCadence = now; + } else if (lastGoodCadence.msecsTo(now) > 2000) { Cadence = 0; } emit cadenceChanged(Cadence.value()); @@ -228,12 +229,12 @@ void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characterist } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); double ac = 0.01243107769; @@ -266,7 +267,7 @@ void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characterist settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); @@ -275,7 +276,7 @@ void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characterist LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (!noVirtualDevice) { #ifdef Q_OS_IOS diff --git a/src/domyosbike.cpp b/src/domyosbike.cpp index 068f4409a..66baa946d 100644 --- a/src/domyosbike.cpp +++ b/src/domyosbike.cpp @@ -283,6 +283,7 @@ void domyosbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void domyosbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -400,7 +401,7 @@ void domyosbike::characteristicChanged(const QLowEnergyCharacteristic &character CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_IOS #ifndef IO_UNDER_QT @@ -433,7 +434,7 @@ void domyosbike::characteristicChanged(const QLowEnergyCharacteristic &character } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } KCal = kcal; Distance = distance; diff --git a/src/domyosrower.cpp b/src/domyosrower.cpp index 8586d030d..42e74e82c 100644 --- a/src/domyosrower.cpp +++ b/src/domyosrower.cpp @@ -40,6 +40,11 @@ void domyosrower::writeCharacteristic(uint8_t *data, uint8_t data_len, const QSt QEventLoop loop; QTimer timeout; + if(ftmsRower) { + qDebug() << "ftmsRower! so don't send anything!"; + return; + } + if (wait_for_response) { connect(gattCommunicationChannelService, &QLowEnergyService::characteristicChanged, &loop, &QEventLoop::quit); timeout.singleShot(300ms, &loop, &QEventLoop::quit); @@ -161,7 +166,8 @@ void domyosrower::update() { initRequest = false; // if(bike_type == CHANG_YOW) - btinit_changyow(false); + if(!ftmsRower) + btinit_changyow(false); // else // btinit_telink(false); } else if (bluetoothDevice.isValid() && m_control->state() == QLowEnergyController::DiscoveredState && @@ -180,6 +186,22 @@ void domyosrower::update() { bool virtual_device_force_bike = settings.value(QZSettings::virtual_device_force_bike, QZSettings::default_virtual_device_force_bike) .toBool(); +#ifdef Q_OS_IOS +#ifndef IO_UNDER_QT + bool cadence = + settings.value(QZSettings::bike_cadence_sensor, QZSettings::default_bike_cadence_sensor).toBool(); + bool ios_peloton_workaround = + settings.value(QZSettings::ios_peloton_workaround, QZSettings::default_ios_peloton_workaround).toBool(); + if (ios_peloton_workaround && cadence) { + + qDebug() << "ios_peloton_workaround activated!"; + h = new lockscreen(); + h->virtualbike_ios(); + } else + +#endif +#endif + { if (virtual_device_enabled) { if (virtual_device_rower) { qDebug() << QStringLiteral("creating virtual rower interface..."); @@ -202,9 +224,11 @@ void domyosrower::update() { connect(virtualBike, &virtualbike::changeInclination, this, &domyosrower::changeInclination); this->setVirtualDevice(virtualBike, VIRTUAL_DEVICE_MODE::ALTERNATIVE); } - firstVirtual = 1; + } } } + firstVirtual = 1; + // ******************************************************************************************************** // updating the treadmill console every second @@ -274,94 +298,345 @@ void domyosrower::serviceDiscovered(const QBluetoothUuid &gatt) { } void domyosrower::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { - // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); + QDateTime now = QDateTime::currentDateTime(); + qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; QString heartRateBeltName = settings.value(QZSettings::heart_rate_belt_name, QZSettings::default_heart_rate_belt_name).toString(); - - emit debug(QStringLiteral(" << ") + newValue.toHex(' ')); + bool disable_hr_frommachinery = + settings.value(QZSettings::heart_ignore_builtin, QZSettings::default_heart_ignore_builtin).toBool(); lastPacket = newValue; - if (newValue.length() != 26) { - return; - } + if(!ftmsRower) { + if (newValue.length() != 26) { + return; + } - if (newValue.at(22) == 0x06) { - emit debug(QStringLiteral("inclination up button pressed!")); + if (newValue.at(22) == 0x06) { + emit debug(QStringLiteral("inclination up button pressed!")); - // requestStart = 1; - } else if (newValue.at(22) == 0x07) { - emit debug(QStringLiteral("inclination down button pressed!")); // i guess it should be the inclination down + // requestStart = 1; + } else if (newValue.at(22) == 0x07) { + emit debug(QStringLiteral("inclination down button pressed!")); // i guess it should be the inclination down - // requestStop = 1; - } + // requestStop = 1; + } - /*if ((uint8_t)newValue.at(1) != 0xbc && newValue.at(2) != 0x04) // intense run, these are the bytes for the - inclination and speed status return;*/ - - double speed = - GetSpeedFromPacket(newValue) * - settings.value(QZSettings::domyos_elliptical_speed_ratio, QZSettings::default_domyos_elliptical_speed_ratio) - .toDouble(); - double kcal = GetKcalFromPacket(newValue); - double distance = - GetDistanceFromPacket(newValue) * - settings.value(QZSettings::domyos_elliptical_speed_ratio, QZSettings::default_domyos_elliptical_speed_ratio) - .toDouble(); - - if (settings.value(QZSettings::cadence_sensor_name, QZSettings::default_cadence_sensor_name) - .toString() - .startsWith(QStringLiteral("Disabled"))) { - Cadence = ((uint8_t)newValue.at(9)); - } - Resistance = newValue.at(14); - Inclination = newValue.at(21); - if (Resistance.value() < 1) { - emit debug(QStringLiteral("invalid resistance value ") + QString::number(Resistance.value()) + - QStringLiteral(" putting to default")); - Resistance = 1; - } - if (Inclination.value() < 0 || Inclination.value() > 15) { - emit debug(QStringLiteral("invalid inclination value ") + QString::number(Inclination.value()) + - QStringLiteral(" putting to default")); - Inclination.setValue(0); - } + /*if ((uint8_t)newValue.at(1) != 0xbc && newValue.at(2) != 0x04) // intense run, these are the bytes for the + inclination and speed status return;*/ + + double speed = + GetSpeedFromPacket(newValue) * + settings.value(QZSettings::domyos_elliptical_speed_ratio, QZSettings::default_domyos_elliptical_speed_ratio) + .toDouble(); + double kcal = GetKcalFromPacket(newValue); + double distance = + GetDistanceFromPacket(newValue) * + settings.value(QZSettings::domyos_elliptical_speed_ratio, QZSettings::default_domyos_elliptical_speed_ratio) + .toDouble(); + + if (settings.value(QZSettings::cadence_sensor_name, QZSettings::default_cadence_sensor_name) + .toString() + .startsWith(QStringLiteral("Disabled"))) { + Cadence = ((uint8_t)newValue.at(9)); + } + Resistance = newValue.at(14); + Inclination = newValue.at(21); + if (Resistance.value() < 1) { + emit debug(QStringLiteral("invalid resistance value ") + QString::number(Resistance.value()) + + QStringLiteral(" putting to default")); + Resistance = 1; + } + if (Inclination.value() < 0 || Inclination.value() > 15) { + emit debug(QStringLiteral("invalid inclination value ") + QString::number(Inclination.value()) + + QStringLiteral(" putting to default")); + Inclination.setValue(0); + } + + #ifdef Q_OS_ANDROID + if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) + Heart = (uint8_t)KeepAwakeHelper::heart(); + else + #endif + { + if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) { + Heart = ((uint8_t)newValue.at(18)); + } + } + + CrankRevs++; + LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); + + emit debug(QStringLiteral("Current speed: ") + QString::number(speed)); + emit debug(QStringLiteral("Current cadence: ") + QString::number(Cadence.value())); + emit debug(QStringLiteral("Current resistance: ") + QString::number(Resistance.value())); + emit debug(QStringLiteral("Current inclination: ") + QString::number(Inclination.value())); + emit debug(QStringLiteral("Current heart: ") + QString::number(Heart.value())); + emit debug(QStringLiteral("Current KCal: ") + QString::number(kcal)); + emit debug(QStringLiteral("Current Distance: ") + QString::number(distance)); + emit debug(QStringLiteral("Current CrankRevs: ") + QString::number(CrankRevs)); + emit debug(QStringLiteral("Last CrankEventTime: ") + QString::number(LastCrankEventTime)); + emit debug(QStringLiteral("Current Watt: ") + QString::number(watts())); + + if (m_control->error() != QLowEnergyController::NoError) { + qDebug() << QStringLiteral("QLowEnergyController ERROR!!") << m_control->errorString(); + } + + Speed = speed; + KCal = kcal; + Distance += ((Speed.value() / 3600000.0) * + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); + lastRefreshCharacteristicChanged = now; + } else { + union flags { + struct { + + uint16_t moreData : 1; + uint16_t avgStroke : 1; + uint16_t totDistance : 1; + uint16_t instantPace : 1; + uint16_t avgPace : 1; + uint16_t instantPower : 1; + uint16_t avgPower : 1; + uint16_t resistanceLvl : 1; + uint16_t expEnergy : 1; + uint16_t heartRate : 1; + uint16_t metabolic : 1; + uint16_t elapsedTime : 1; + uint16_t remainingTime : 1; + uint16_t spare : 3; + }; + + uint16_t word_flags; + }; + + flags Flags; + int index = 0; + double cadence_divider = 2.0; + if(newValue.length() < 2) { + qDebug() << "index out of range" << 0; + return; + } + Flags.word_flags = (newValue.at(1) << 8) | newValue.at(0); + index += 2; + + if (!Flags.moreData) { + + if(index >= newValue.length()) { + qDebug() << "index out of range" << index; + return; + } + Cadence = ((uint8_t)newValue.at(index)) / cadence_divider; + + if(index + 2 >= newValue.length()) { + qDebug() << "index out of range" << index; + return; + } + StrokesCount = + (((uint16_t)((uint8_t)newValue.at(index + 2)) << 8) | (uint16_t)((uint8_t)newValue.at(index + 1))); + + if (lastStrokesCount != StrokesCount.value()) { + lastStroke = now; + } + lastStrokesCount = StrokesCount.value(); + + index += 3; + + /* + * the concept 2 sends the pace in 2 frames, so this condition will create a bogus speed + if (!Flags.instantPace) { + // eredited by echelon rower, probably we need to change this + Speed = (0.37497622 * ((double)Cadence.value())) / 2.0; + emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); + }*/ + emit debug(QStringLiteral("Strokes Count: ") + QString::number(StrokesCount.value())); + } + + if (Flags.avgStroke) { + + double avgStroke; + if(index >= newValue.length()) { + qDebug() << "index out of range" << index; + return; + } + avgStroke = ((double)(uint16_t)((uint8_t)newValue.at(index))) / cadence_divider; + index += 1; + emit debug(QStringLiteral("Current Average Stroke: ") + QString::number(avgStroke)); + } + + if (Flags.totDistance) { + if(index + 2 >= newValue.length()) { + qDebug() << "index out of range" << index; + return; + } + Distance = ((double)((((uint32_t)((uint8_t)newValue.at(index + 2)) << 16) | + (uint32_t)((uint8_t)newValue.at(index + 1)) << 8) | + (uint32_t)((uint8_t)newValue.at(index)))) / + 1000.0; + index += 3; + } else { + Distance += ((Speed.value() / 3600000.0) * + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); + } + + emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); + + if (Flags.instantPace) { + + if(index + 1 >= newValue.length()) { + qDebug() << "index out of range" << index; + return; + } + + double instantPace; + instantPace = + ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | (uint16_t)((uint8_t)newValue.at(index)))); + index += 2; + emit debug(QStringLiteral("Current Pace: ") + QString::number(instantPace)); + + Speed = (60.0 / instantPace) * + 30.0; // translating pace (min/500m) to km/h in order to match the pace function in the rower.cpp + emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); + } + + if (Flags.avgPace) { + + if(index + 1>= newValue.length()) { + qDebug() << "index out of range" << index; + return; + } + + double avgPace; + avgPace = + ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | (uint16_t)((uint8_t)newValue.at(index)))); + index += 2; + emit debug(QStringLiteral("Current Average Pace: ") + QString::number(avgPace)); + } + + if (Flags.instantPower) { + if(index + 1 >= newValue.length()) { + qDebug() << "index out of range" << index; + return; + } + + double watt = + ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | (uint16_t)((uint8_t)newValue.at(index)))); + index += 2; + m_watt = watt; + emit debug(QStringLiteral("Current Watt: ") + QString::number(m_watt.value())); + } + + if (Flags.avgPower) { + if(index + 1 >= newValue.length()) { + qDebug() << "index out of range" << index; + return; + } + + double avgPower; + avgPower = + ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | (uint16_t)((uint8_t)newValue.at(index)))); + index += 2; + emit debug(QStringLiteral("Current Average Watt: ") + QString::number(avgPower)); + } + + if (Flags.resistanceLvl) { + if(index + 1 >= newValue.length()) { + qDebug() << "index out of range" << index; + return; + } + Resistance = + ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | (uint16_t)((uint8_t)newValue.at(index)))); + emit resistanceRead(Resistance.value()); + index += 2; + emit debug(QStringLiteral("Current Resistance: ") + QString::number(Resistance.value())); + } + + if (Flags.expEnergy && index + 1 < newValue.length()) { + KCal = ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | (uint16_t)((uint8_t)newValue.at(index)))); + index += 2; + + // energy per hour + index += 2; + + // energy per minute + index += 1; + } else { + if (watts()) + KCal += + ((((0.048 * ((double)watts()) + 1.19) * + settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / + 200.0) / + (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( + now)))); //(( (0.048* Output in watts +1.19) * body weight in + // kg * 3.5) / 200 ) / 60 + } + + emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); + + #ifdef Q_OS_ANDROID + if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) + Heart = (uint8_t)KeepAwakeHelper::heart(); + else + #endif + { + if (Flags.heartRate && !disable_hr_frommachinery) { + if (index < newValue.length()) { + Heart = ((double)(((uint8_t)newValue.at(index)))); + // index += 1; //NOTE: clang-analyzer-deadcode.DeadStores + emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); + } else + emit debug(QStringLiteral("Error on parsing heart")); + } + } + + if (Flags.metabolic) { + + // todo + } + + if (Flags.elapsedTime) { + + // todo + } + + if (Flags.remainingTime) { + + // todo + } + + if (Cadence.value() > 0) { + + CrankRevs++; + LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); + } + + lastRefreshCharacteristicChanged = now; -#ifdef Q_OS_ANDROID - if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) - Heart = (uint8_t)KeepAwakeHelper::heart(); - else -#endif - { if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) { - Heart = ((uint8_t)newValue.at(18)); + update_hr_from_external(); } - } - CrankRevs++; - LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); - - emit debug(QStringLiteral("Current speed: ") + QString::number(speed)); - emit debug(QStringLiteral("Current cadence: ") + QString::number(Cadence.value())); - emit debug(QStringLiteral("Current resistance: ") + QString::number(Resistance.value())); - emit debug(QStringLiteral("Current inclination: ") + QString::number(Inclination.value())); - emit debug(QStringLiteral("Current heart: ") + QString::number(Heart.value())); - emit debug(QStringLiteral("Current KCal: ") + QString::number(kcal)); - emit debug(QStringLiteral("Current Distance: ") + QString::number(distance)); - emit debug(QStringLiteral("Current CrankRevs: ") + QString::number(CrankRevs)); - emit debug(QStringLiteral("Last CrankEventTime: ") + QString::number(LastCrankEventTime)); - emit debug(QStringLiteral("Current Watt: ") + QString::number(watts())); - - if (m_control->error() != QLowEnergyController::NoError) { - qDebug() << QStringLiteral("QLowEnergyController ERROR!!") << m_control->errorString(); - } + #ifdef Q_OS_IOS + #ifndef IO_UNDER_QT + bool cadence = settings.value(QZSettings::bike_cadence_sensor, QZSettings::default_bike_cadence_sensor).toBool(); + bool ios_peloton_workaround = + settings.value(QZSettings::ios_peloton_workaround, QZSettings::default_ios_peloton_workaround).toBool(); + if (ios_peloton_workaround && cadence && h && firstVirtual) { + + h->virtualbike_setCadence(currentCrankRevolutions(), lastCrankEventTime()); + h->virtualbike_setHeartRate((uint8_t)metrics_override_heartrate()); + } + #endif + #endif + + emit debug(QStringLiteral("Current CrankRevs: ") + QString::number(CrankRevs)); + emit debug(QStringLiteral("Last CrankEventTime: ") + QString::number(LastCrankEventTime)); - Speed = speed; - KCal = kcal; - Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + if (m_control->error() != QLowEnergyController::NoError) { + qDebug() << QStringLiteral("QLowEnergyController ERROR!!") << m_control->errorString(); + } + } } double domyosrower::GetSpeedFromPacket(const QByteArray &packet) { @@ -457,40 +732,133 @@ void domyosrower::btinit_telink(bool startTape) { } void domyosrower::stateChanged(QLowEnergyService::ServiceState state) { - QBluetoothUuid _gattWriteCharacteristicId(QStringLiteral("49535343-8841-43f4-a8d4-ecbe34729bb3")); - QBluetoothUuid _gattNotifyCharacteristicId(QStringLiteral("49535343-1e4d-4bd9-ba61-23c647249616")); - - QMetaEnum metaEnum = QMetaEnum::fromType(); - emit debug(QStringLiteral("BTLE stateChanged ") + QString::fromLocal8Bit(metaEnum.valueToKey(state))); - - if (state == QLowEnergyService::ServiceDiscovered) { - - // qDebug() << gattCommunicationChannelService->characteristics(); - - gattWriteCharacteristic = gattCommunicationChannelService->characteristic(_gattWriteCharacteristicId); - gattNotifyCharacteristic = gattCommunicationChannelService->characteristic(_gattNotifyCharacteristicId); - Q_ASSERT(gattWriteCharacteristic.isValid()); - Q_ASSERT(gattNotifyCharacteristic.isValid()); - - // establish hook into notifications - connect(gattCommunicationChannelService, &QLowEnergyService::characteristicChanged, this, - &domyosrower::characteristicChanged); - connect(gattCommunicationChannelService, &QLowEnergyService::characteristicWritten, this, - &domyosrower::characteristicWritten); - connect(gattCommunicationChannelService, - static_cast(&QLowEnergyService::error), - this, &domyosrower::errorService); - connect(gattCommunicationChannelService, &QLowEnergyService::descriptorWritten, this, - &domyosrower::descriptorWritten); - - QByteArray descriptor; - descriptor.append((char)0x01); - descriptor.append((char)0x00); - gattCommunicationChannelService->writeDescriptor( - gattNotifyCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), descriptor); + if(!ftmsRower) { + QBluetoothUuid _gattWriteCharacteristicId(QStringLiteral("49535343-8841-43f4-a8d4-ecbe34729bb3")); + QBluetoothUuid _gattNotifyCharacteristicId(QStringLiteral("49535343-1e4d-4bd9-ba61-23c647249616")); + + QMetaEnum metaEnum = QMetaEnum::fromType(); + emit debug(QStringLiteral("BTLE stateChanged ") + QString::fromLocal8Bit(metaEnum.valueToKey(state))); + + if (state == QLowEnergyService::ServiceDiscovered) { + + // qDebug() << gattCommunicationChannelService->characteristics(); + + gattWriteCharacteristic = gattCommunicationChannelService->characteristic(_gattWriteCharacteristicId); + gattNotifyCharacteristic = gattCommunicationChannelService->characteristic(_gattNotifyCharacteristicId); + Q_ASSERT(gattWriteCharacteristic.isValid()); + Q_ASSERT(gattNotifyCharacteristic.isValid()); + + // establish hook into notifications + connect(gattCommunicationChannelService, &QLowEnergyService::characteristicChanged, this, + &domyosrower::characteristicChanged); + connect(gattCommunicationChannelService, &QLowEnergyService::characteristicWritten, this, + &domyosrower::characteristicWritten); + connect(gattCommunicationChannelService, + static_cast(&QLowEnergyService::error), + this, &domyosrower::errorService); + connect(gattCommunicationChannelService, &QLowEnergyService::descriptorWritten, this, + &domyosrower::descriptorWritten); + + QByteArray descriptor; + descriptor.append((char)0x01); + descriptor.append((char)0x00); + gattCommunicationChannelService->writeDescriptor( + gattNotifyCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), descriptor); + } + } else { + QMetaEnum metaEnum = QMetaEnum::fromType(); + emit debug(QStringLiteral("BTLE stateChanged ") + QString::fromLocal8Bit(metaEnum.valueToKey(state))); + + for (QLowEnergyService *s : qAsConst(gattCommunicationChannelServiceArray)) { + qDebug() << QStringLiteral("stateChanged") << s->serviceUuid() << s->state(); + if (s->state() != QLowEnergyService::ServiceDiscovered && s->state() != QLowEnergyService::InvalidService) { + qDebug() << QStringLiteral("not all services discovered"); + + return; + } + } + + qDebug() << QStringLiteral("all services discovered!"); + + for (QLowEnergyService *s : qAsConst(gattCommunicationChannelServiceArray)) { + if (s->state() == QLowEnergyService::ServiceDiscovered) { + + // establish hook into notifications + connect(s, &QLowEnergyService::characteristicChanged, this, &domyosrower::characteristicChanged); + connect(s, &QLowEnergyService::characteristicWritten, this, &domyosrower::characteristicWritten); + connect(s, &QLowEnergyService::characteristicRead, this, &domyosrower::characteristicRead); + connect( + s, static_cast(&QLowEnergyService::error), + this, &domyosrower::errorService); + connect(s, &QLowEnergyService::descriptorWritten, this, &domyosrower::descriptorWritten); + connect(s, &QLowEnergyService::descriptorRead, this, &domyosrower::descriptorRead); + + qDebug() << s->serviceUuid() << QStringLiteral("connected!"); + + auto characteristics_list = s->characteristics(); + for (const QLowEnergyCharacteristic &c : qAsConst(characteristics_list)) { + qDebug() << "char uuid" << c.uuid() << QStringLiteral("handle") << c.handle(); + auto descriptors_list = c.descriptors(); + for (const QLowEnergyDescriptor &d : qAsConst(descriptors_list)) { + qDebug() << QStringLiteral("descriptor uuid") << d.uuid() << QStringLiteral("handle") << d.handle(); + } + + if ((c.properties() & QLowEnergyCharacteristic::Notify) == QLowEnergyCharacteristic::Notify) { + + QByteArray descriptor; + descriptor.append((char)0x01); + descriptor.append((char)0x00); + if (c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).isValid()) { + s->writeDescriptor(c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), descriptor); + } else { + qDebug() << QStringLiteral("ClientCharacteristicConfiguration") << c.uuid() + << c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).uuid() + << c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).handle() + << QStringLiteral(" is not valid"); + } + + qDebug() << s->serviceUuid() << c.uuid() << QStringLiteral("notification subscribed!"); + } else if ((c.properties() & QLowEnergyCharacteristic::Indicate) == + QLowEnergyCharacteristic::Indicate) { + QByteArray descriptor; + descriptor.append((char)0x02); + descriptor.append((char)0x00); + if (c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).isValid()) { + s->writeDescriptor(c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), descriptor); + } else { + qDebug() << QStringLiteral("ClientCharacteristicConfiguration") << c.uuid() + << c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).uuid() + << c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).handle() + << QStringLiteral(" is not valid"); + } + + qDebug() << s->serviceUuid() << c.uuid() << QStringLiteral("indication subscribed!"); + } else if ((c.properties() & QLowEnergyCharacteristic::Read) == QLowEnergyCharacteristic::Read) { + // s->readCharacteristic(c); + // qDebug() << s->serviceUuid() << c.uuid() << "reading!"; + } + + QBluetoothUuid _gattWriteCharControlPointId((quint16)0x2AD9); + if (c.properties() & QLowEnergyCharacteristic::Write && c.uuid() == _gattWriteCharControlPointId) { + qDebug() << QStringLiteral("FTMS service and Control Point found"); + + gattWriteCharControlPointId = c; + gattFTMSService = s; + } + } + } + } } } +void domyosrower::descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue) { + qDebug() << QStringLiteral("descriptorRead ") << descriptor.name() << descriptor.uuid() << newValue.toHex(' '); +} + +void domyosrower::characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + qDebug() << QStringLiteral("characteristicRead ") << characteristic.uuid() << newValue.toHex(' '); +} + void domyosrower::searchingStop() { searchStopped = true; } void domyosrower::descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue) { @@ -511,8 +879,19 @@ void domyosrower::serviceScanDone(void) { QBluetoothUuid _gattCommunicationChannelServiceId(QStringLiteral("49535343-fe7d-4ae5-8fa9-9fafd205e455")); gattCommunicationChannelService = m_control->createServiceObject(_gattCommunicationChannelServiceId); - connect(gattCommunicationChannelService, &QLowEnergyService::stateChanged, this, &domyosrower::stateChanged); - gattCommunicationChannelService->discoverDetails(); + if(gattCommunicationChannelService) { + connect(gattCommunicationChannelService, &QLowEnergyService::stateChanged, this, &domyosrower::stateChanged); + gattCommunicationChannelService->discoverDetails(); + } else { + ftmsRower = true; + auto services_list = m_control->services(); + for (const QBluetoothUuid &s : qAsConst(services_list)) { + gattCommunicationChannelServiceArray.append(m_control->createServiceObject(s)); + connect(gattCommunicationChannelServiceArray.constLast(), &QLowEnergyService::stateChanged, this, + &domyosrower::stateChanged); + gattCommunicationChannelServiceArray.constLast()->discoverDetails(); + } + } } void domyosrower::errorService(QLowEnergyService::ServiceError err) { diff --git a/src/domyosrower.h b/src/domyosrower.h index 2d44d6608..e8f0e8619 100644 --- a/src/domyosrower.h +++ b/src/domyosrower.h @@ -28,6 +28,10 @@ #include "rower.h" +#ifdef Q_OS_IOS +#include "ios/lockscreen.h" +#endif + class domyosrower : public rower { Q_OBJECT public: @@ -58,11 +62,16 @@ class domyosrower : public rower { QLowEnergyCharacteristic gattWriteCharacteristic; QLowEnergyCharacteristic gattNotifyCharacteristic; + QList gattCommunicationChannelServiceArray; + QLowEnergyCharacteristic gattWriteCharControlPointId; + QLowEnergyService *gattFTMSService = nullptr; + bool initDone = false; bool initRequest = false; bool noWriteResistance = false; bool noHeartService = false; bool testResistance = false; + bool ftmsRower = false; uint8_t bikeResistanceOffset = 4; double bikeResistanceGain = 1.0; bool searchStopped = false; @@ -70,6 +79,13 @@ class domyosrower : public rower { QByteArray lastPacket; QDateTime lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + QDateTime lastStroke = QDateTime::currentDateTime(); + double lastStrokesCount = 0; + +#ifdef Q_OS_IOS + lockscreen *h = 0; +#endif + enum _BIKE_TYPE { CHANG_YOW, TELINK, @@ -86,6 +102,8 @@ class domyosrower : public rower { private slots: + void characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue); + void descriptorRead(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue); void characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue); void characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue); void descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue); diff --git a/src/echelonrower.cpp b/src/echelonrower.cpp index a1659f4da..088c4d966 100644 --- a/src/echelonrower.cpp +++ b/src/echelonrower.cpp @@ -25,6 +25,7 @@ echelonrower::echelonrower(bool noWriteResistance, bool noHeartService, uint8_t #endif m_watt.setType(metric::METRIC_WATT); Speed.setType(metric::METRIC_SPEED); + speedRaw.setType(metric::METRIC_SPEED); refresh = new QTimer(this); this->noWriteResistance = noWriteResistance; this->noHeartService = noHeartService; @@ -236,10 +237,13 @@ void echelonrower::characteristicChanged(const QLowEnergyCharacteristic &charact ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())) / 60000; } // instant pace to km/h - if (((uint8_t)lastPacket.at(14)) > 0 && Cadence.value() > 0) - Speed = (60.0 / (double)((uint8_t)lastPacket.at(14))) * 30.0; - else + if ((((uint8_t)lastPacket.at(14)) > 0 || ((uint8_t)lastPacket.at(13)) > 0) && Cadence.value() > 0) { + speedRaw = (60.0 / (double)(((uint16_t)lastPacket.at(13) << 8) | ((uint16_t)lastPacket.at(14)))) * 30.0; + Speed = speedRaw.average5s(); + } else { Speed = 0; + speedRaw = 0; + } StrokesLength = ((Speed.value() / 60.0) * 1000.0) / diff --git a/src/echelonrower.h b/src/echelonrower.h index 96a5a0477..502bd3ca0 100644 --- a/src/echelonrower.h +++ b/src/echelonrower.h @@ -76,6 +76,7 @@ class echelonrower : public rower { bool noWriteResistance = false; bool noHeartService = false; + metric speedRaw; #ifdef Q_OS_IOS lockscreen *h = 0; diff --git a/src/echelonstride.cpp b/src/echelonstride.cpp index 1ec34dee5..868cacc52 100644 --- a/src/echelonstride.cpp +++ b/src/echelonstride.cpp @@ -237,6 +237,7 @@ void echelonstride::serviceDiscovered(const QBluetoothUuid &gatt) { double echelonstride::minStepInclination() { return 1.0; } void echelonstride::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); QSettings settings; QString heartRateBeltName = @@ -300,10 +301,10 @@ void echelonstride::characteristicChanged(const QLowEnergyCharacteristic &charac settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastTimeCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600.0) / - (1000.0 / (lastTimeCharacteristicChanged.msecsTo(QDateTime::currentDateTime())))); + (1000.0 / (lastTimeCharacteristicChanged.msecsTo(now)))); } if ((uint8_t)newValue.at(1) == 0xD1 && newValue.length() > 11) @@ -334,7 +335,7 @@ void echelonstride::characteristicChanged(const QLowEnergyCharacteristic &charac if (m_control->error() != QLowEnergyController::NoError) qDebug() << QStringLiteral("QLowEnergyController ERROR!!") << m_control->errorString(); - lastTimeCharacteristicChanged = QDateTime::currentDateTime(); + lastTimeCharacteristicChanged = now; firstCharacteristicChanged = false; } diff --git a/src/eliteariafan.cpp b/src/eliteariafan.cpp new file mode 100644 index 000000000..759b6181b --- /dev/null +++ b/src/eliteariafan.cpp @@ -0,0 +1,334 @@ +#include "eliteariafan.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std::chrono_literals; + +#ifdef Q_OS_IOS +extern quint8 QZ_EnableDiscoveryCharsAndDescripttors; +#endif + +// this module on iOS is completely handled from the ObjectiveC module in order to test if it's more stable than the Qt Bluetooth Implementation (crash midride) + +eliteariafan::eliteariafan(bluetoothdevice *parentDevice) { +#ifdef Q_OS_IOS + QZ_EnableDiscoveryCharsAndDescripttors = true; +#endif + this->parentDevice = parentDevice; + +#ifndef Q_OS_IOS + refresh = new QTimer(this); + connect(refresh, &QTimer::timeout, this, &eliteariafan::update); + refresh->start(1000ms); +#endif +} + +void eliteariafan::update() { + if (initRequest) { + initRequest = false; + + uint8_t init1[] = {0x02, 0x00, 0x00, 0x3d, 0x00}; + writeCharacteristic(gattWrite1Service, &gattWrite1Characteristic, init1, sizeof(init1), "init", false, true); + + uint8_t init2[] = {0x05, 0x00}; + writeCharacteristic(gattWrite1Service, &gattWrite2Characteristic, init2, sizeof(init2), "init", false, true); + + initDone = true; + } +} + +void eliteariafan::serviceDiscovered(const QBluetoothUuid &gatt) { + emit debug(QStringLiteral("serviceDiscovered ") + gatt.toString()); +} + +void eliteariafan::disconnectBluetooth() { + qDebug() << QStringLiteral("eliteariafan::disconnect") << m_control; + + if (m_control) { + m_control->disconnectFromDevice(); + } +} + +void eliteariafan::characteristicChanged(const QLowEnergyCharacteristic &characteristic, + const QByteArray &newValue) { + Q_UNUSED(characteristic); + emit packetReceived(); + + qDebug() << QStringLiteral(" << ") << newValue.toHex(' '); +} + +void eliteariafan::fanSpeedRequest(uint8_t speed) { + QSettings settings; + if (speed > 100) + speed = 100; + double max = settings.value(QZSettings::fitmetria_fanfit_max, QZSettings::default_fitmetria_fanfit_max).toDouble(); + double min = settings.value(QZSettings::fitmetria_fanfit_min, QZSettings::default_fitmetria_fanfit_min).toDouble(); + + uint16_t speed8 = (uint8_t)((double)speed * (max - min) / 100.0 + min); + +#ifdef Q_OS_IOS +#ifndef IO_UNDER_QT + iOS_EliteAriaFan->eliteAriaFan_fanSpeedRequest(speed8); +#endif +#else + uint8_t init10[] = {0x03, 0x01, 0x0e}; + init10[2] = speed8; + writeCharacteristic(gattWrite1Service, &gattWrite2Characteristic, init10, sizeof(init10), + "forcing fan" + QString::number(speed)); +#endif +} + +void eliteariafan::writeCharacteristic(QLowEnergyService *service, QLowEnergyCharacteristic *writeChar, + uint8_t *data, uint8_t data_len, const QString &info, bool disable_log, + bool wait_for_response) { + QEventLoop loop; + QTimer timeout; + + if (service == nullptr || writeChar->isValid() == false) { + qDebug() << QStringLiteral( + "eliteariafan trying to change the fan speed before the connection is estabilished"); + return; + } + + // if there are some crash here, maybe it's better to use 2 separate event for the characteristicChanged. + // one for the resistance changed event (spontaneous), and one for the other ones. + if (wait_for_response) { + connect(service, &QLowEnergyService::characteristicChanged, &loop, &QEventLoop::quit); + timeout.singleShot(300ms, &loop, &QEventLoop::quit); + } else { + connect(service, &QLowEnergyService::characteristicWritten, &loop, &QEventLoop::quit); + timeout.singleShot(300ms, &loop, &QEventLoop::quit); + } + + if (service->state() != QLowEnergyService::ServiceState::ServiceDiscovered || + m_control->state() == QLowEnergyController::UnconnectedState) { + qDebug() << QStringLiteral("writeCharacteristic error because the connection is closed"); + return; + } + + if (!writeChar->isValid()) { + qDebug() << QStringLiteral("gattWriteCharacteristic is invalid"); + return; + } + + if (writeBuffer) { + delete writeBuffer; + } + writeBuffer = new QByteArray((const char *)data, data_len); + + service->writeCharacteristic(*writeChar, *writeBuffer, QLowEnergyService::WriteWithoutResponse); + + if (!disable_log) { + qDebug() << QStringLiteral(" >> ") + writeBuffer->toHex(' ') + QStringLiteral(" // ") + info; + } + + loop.exec(); +} + +void eliteariafan::stateChanged(QLowEnergyService::ServiceState state) { + QBluetoothUuid _gattWriteCharacteristicId1(QStringLiteral("347b0012-7635-408b-8918-8ff3949ce592")); // handle 0x1d + QBluetoothUuid _gattWriteCharacteristicId2(QStringLiteral("347b0040-7635-408b-8918-8ff3949ce592")); // handle 0x27 + + QMetaEnum metaEnum = QMetaEnum::fromType(); + emit debug(QStringLiteral("BTLE stateChanged ") + QString::fromLocal8Bit(metaEnum.valueToKey(state))); + + for (QLowEnergyService *s : qAsConst(gattCommunicationChannelService)) { + qDebug() << QStringLiteral("stateChanged") << s->serviceUuid() << s->state(); + if (s->state() != QLowEnergyService::ServiceDiscovered && s->state() != QLowEnergyService::InvalidService) { + qDebug() << QStringLiteral("not all services discovered"); + return; + } + } + + if (state != QLowEnergyService::ServiceState::ServiceDiscovered) { + qDebug() << QStringLiteral("ignoring this state"); + return; + } + + qDebug() << QStringLiteral("all services discovered!"); + + for (QLowEnergyService *s : qAsConst(gattCommunicationChannelService)) { + if (s->state() == QLowEnergyService::ServiceDiscovered) { + // establish hook into notifications + connect(s, &QLowEnergyService::characteristicChanged, this, &eliteariafan::characteristicChanged); + connect(s, &QLowEnergyService::characteristicWritten, this, &eliteariafan::characteristicWritten); + connect( + s, static_cast(&QLowEnergyService::error), + this, &eliteariafan::errorService); + connect(s, &QLowEnergyService::descriptorWritten, this, &eliteariafan::descriptorWritten); + + qDebug() << s->serviceUuid() << QStringLiteral("connected!"); + + auto characteristics_list = s->characteristics(); + for (const QLowEnergyCharacteristic &c : qAsConst(characteristics_list)) { + qDebug() << QStringLiteral("char uuid") << c.uuid() << QStringLiteral("handle") << c.handle(); + auto descriptors_list = c.descriptors(); + for (const QLowEnergyDescriptor &d : qAsConst(descriptors_list)) { + qDebug() << QStringLiteral("descriptor uuid") << d.uuid() << QStringLiteral("handle") << d.handle(); + } + + if ((c.properties() & QLowEnergyCharacteristic::Notify) == QLowEnergyCharacteristic::Notify) { + QByteArray descriptor; + descriptor.append((char)0x01); + descriptor.append((char)0x00); + if (c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).isValid()) { + s->writeDescriptor(c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), descriptor); + } else { + qDebug() << QStringLiteral("ClientCharacteristicConfiguration") << c.uuid() + << c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).uuid() + << c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).handle() + << QStringLiteral(" is not valid"); + } + + qDebug() << s->serviceUuid() << c.uuid() << QStringLiteral("notification subscribed!"); + } else if ((c.properties() & QLowEnergyCharacteristic::Indicate) == + QLowEnergyCharacteristic::Indicate) { + QByteArray descriptor; + descriptor.append((char)0x02); + descriptor.append((char)0x00); + if (c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).isValid()) { + s->writeDescriptor(c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration), descriptor); + } else { + qDebug() << QStringLiteral("ClientCharacteristicConfiguration") << c.uuid() + << c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).uuid() + << c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration).handle() + << QStringLiteral(" is not valid"); + } + + qDebug() << s->serviceUuid() << c.uuid() << QStringLiteral("indication subscribed!"); + } else if ((c.properties() & QLowEnergyCharacteristic::Read) == QLowEnergyCharacteristic::Read) { + // s->readCharacteristic(c); + // qDebug() << s->serviceUuid() << c.uuid() << "reading!"; + } + + if (c.uuid() == _gattWriteCharacteristicId1) { + qDebug() << QStringLiteral("_gattWriteCharacteristicId1 found"); + gattWrite1Characteristic = c; + gattWrite1Service = s; + } else if (c.uuid() == _gattWriteCharacteristicId2) { + qDebug() << QStringLiteral("_gattWriteCharacteristicId2 found"); + gattWrite2Characteristic = c; + } + } + } + } +} + +void eliteariafan::descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue) { + emit debug(QStringLiteral("descriptorWritten ") + descriptor.name() + " " + newValue.toHex(' ')); + initRequest = true; +} + +void eliteariafan::characteristicWritten(const QLowEnergyCharacteristic &characteristic, + const QByteArray &newValue) { + Q_UNUSED(characteristic); + emit debug(QStringLiteral("characteristicWritten ") + newValue.toHex(' ')); +} + +void eliteariafan::serviceScanDone(void) { + emit debug(QStringLiteral("serviceScanDone")); + + initRequest = false; + + auto services_list = m_control->services(); + for (const QBluetoothUuid &s : qAsConst(services_list)) { + gattCommunicationChannelService.append(m_control->createServiceObject(s)); + if (gattCommunicationChannelService.constLast()) { + connect(gattCommunicationChannelService.constLast(), &QLowEnergyService::stateChanged, this, + &eliteariafan::stateChanged); + gattCommunicationChannelService.constLast()->discoverDetails(); + } else { + m_control->disconnectFromDevice(); + } + } +} + +void eliteariafan::errorService(QLowEnergyService::ServiceError err) { + QMetaEnum metaEnum = QMetaEnum::fromType(); + emit debug(QStringLiteral("eliteariafan::errorService") + QString::fromLocal8Bit(metaEnum.valueToKey(err)) + + m_control->errorString()); +} + +void eliteariafan::error(QLowEnergyController::Error err) { + QMetaEnum metaEnum = QMetaEnum::fromType(); + emit debug(QStringLiteral("eliteariafan::error") + QString::fromLocal8Bit(metaEnum.valueToKey(err)) + + m_control->errorString()); +} + +void eliteariafan::deviceDiscovered(const QBluetoothDeviceInfo &device) { + QSettings settings; + emit debug(QStringLiteral("Found new device: ") + device.name() + QStringLiteral(" (") + + device.address().toString() + ')'); + +#ifdef Q_OS_IOS +#ifndef IO_UNDER_QT + iOS_EliteAriaFan = new lockscreen(); + iOS_EliteAriaFan->eliteAriaFan(); + return; +#endif +#endif + { + bluetoothDevice = device; + m_control = QLowEnergyController::createCentral(bluetoothDevice, this); + connect(m_control, &QLowEnergyController::serviceDiscovered, this, &eliteariafan::serviceDiscovered); + connect(m_control, &QLowEnergyController::discoveryFinished, this, &eliteariafan::serviceScanDone); + connect(m_control, + static_cast(&QLowEnergyController::error), + this, &eliteariafan::error); + connect(m_control, &QLowEnergyController::stateChanged, this, &eliteariafan::controllerStateChanged); + + connect(m_control, + static_cast(&QLowEnergyController::error), + this, [this](QLowEnergyController::Error error) { + Q_UNUSED(error); + Q_UNUSED(this); + emit debug(QStringLiteral("Cannot connect to remote device.")); + emit disconnected(); + }); + connect(m_control, &QLowEnergyController::connected, this, [this]() { + Q_UNUSED(this); + emit debug(QStringLiteral("Controller connected. Search services...")); + m_control->discoverServices(); + }); + connect(m_control, &QLowEnergyController::disconnected, this, [this]() { + Q_UNUSED(this); + emit debug(QStringLiteral("LowEnergy controller disconnected")); + emit disconnected(); + }); + + // Connect + m_control->connectToDevice(); + return; + } +} + +bool eliteariafan::connected() { +#ifdef Q_OS_IOS + return true; +#endif + + if (!m_control) { + return false; + } + return m_control->state() == QLowEnergyController::DiscoveredState; +} + +void eliteariafan::controllerStateChanged(QLowEnergyController::ControllerState state) { +#ifdef Q_OS_IOS + return; +#endif + + qDebug() << QStringLiteral("controllerStateChanged") << state; + if (state == QLowEnergyController::UnconnectedState && m_control) { + qDebug() << QStringLiteral("trying to connect back again..."); + initRequest = false; + initDone = false; + + m_control->connectToDevice(); + } +} diff --git a/src/eliteariafan.h b/src/eliteariafan.h new file mode 100644 index 000000000..8bb29f735 --- /dev/null +++ b/src/eliteariafan.h @@ -0,0 +1,90 @@ +#ifndef ELITEARIAFAN_H +#define ELITEARIAFAN_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef Q_OS_ANDROID +#include +#else +#include +#endif + +#ifdef Q_OS_IOS +#include "ios/lockscreen.h" +#endif + +#include +#include +#include +#include + +#include +#include + +#include "bluetoothdevice.h" + +class eliteariafan : public bluetoothdevice { + Q_OBJECT + public: + eliteariafan(bluetoothdevice *parentDevice); + bool connected() override; + + private: + QList gattCommunicationChannelService; + QLowEnergyCharacteristic gattNotify1Characteristic; + QLowEnergyCharacteristic gattNotify2Characteristic; + QLowEnergyCharacteristic gattWrite1Characteristic; + QLowEnergyService *gattWrite1Service; + QLowEnergyCharacteristic gattWrite2Characteristic; + + void writeCharacteristic(QLowEnergyService *service, QLowEnergyCharacteristic *writeChar, uint8_t *data, + uint8_t data_len, const QString &info, bool disable_log = false, + bool wait_for_response = false); + + bluetoothdevice *parentDevice = nullptr; + + bool initDone = false; + bool initRequest = false; + + QTimer *refresh; + +#ifdef Q_OS_IOS + lockscreen* iOS_EliteAriaFan = nullptr; +#endif + + + signals: + void disconnected(); + void debug(QString string); + void packetReceived(); + + public slots: + void deviceDiscovered(const QBluetoothDeviceInfo &device); + void disconnectBluetooth(); + void fanSpeedRequest(uint8_t value); + + private slots: + + void characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue); + void characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue); + void descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue); + void stateChanged(QLowEnergyService::ServiceState state); + void controllerStateChanged(QLowEnergyController::ControllerState state); + + void serviceDiscovered(const QBluetoothUuid &gatt); + void serviceScanDone(void); + void update(); + void error(QLowEnergyController::Error err); + void errorService(QLowEnergyService::ServiceError); +}; + +#endif // ELITEARIAFAN_H diff --git a/src/elliptical.cpp b/src/elliptical.cpp index 03b3a026b..3127c9d40 100644 --- a/src/elliptical.cpp +++ b/src/elliptical.cpp @@ -108,6 +108,7 @@ void elliptical::clearStats() { Speed.clear(false); KCal.clear(true); Distance.clear(true); + Distance1s.clear(true); Heart.clear(false); m_jouls.clear(true); elevationAcc = 0; @@ -124,6 +125,7 @@ void elliptical::setPaused(bool p) { Speed.setPaused(p); KCal.setPaused(p); Distance.setPaused(p); + Distance1s.setPaused(p); Heart.setPaused(p); m_jouls.setPaused(p); m_watt.setPaused(p); @@ -138,6 +140,7 @@ void elliptical::setLap() { Speed.setLap(false); KCal.setLap(true); Distance.setLap(true); + Distance1s.setLap(true); Heart.setLap(false); m_jouls.setLap(true); m_watt.setLap(false); diff --git a/src/fakebike.cpp b/src/fakebike.cpp index 6bc0f6e09..6c3fcb1ac 100644 --- a/src/fakebike.cpp +++ b/src/fakebike.cpp @@ -49,6 +49,7 @@ void fakebike::update() { if (requestPower != -1) { // bepo70: don't know if this conversion is really needed, i would do it anyway. m_watt = (double)requestPower; + Cadence = requestPower; emit debug(QStringLiteral("writing power ") + QString::number(requestPower)); requestPower = -1; // bepo70: Disregard the current inclination for calculating speed. When the video @@ -60,6 +61,11 @@ void fakebike::update() { m_watt.value(), 0, Speed.value(), fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), speedLimit()); } + + if (Cadence.value() > 0) { + CrankRevs++; + LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); + } if (requestInclination != -100) { Inclination = requestInclination; diff --git a/src/faketreadmill.cpp b/src/faketreadmill.cpp index 5396164f1..9cacef88a 100644 --- a/src/faketreadmill.cpp +++ b/src/faketreadmill.cpp @@ -32,6 +32,7 @@ void faketreadmill::update() { QSettings settings; QString heartRateBeltName = settings.value(QZSettings::heart_rate_belt_name, QZSettings::default_heart_rate_belt_name).toString(); + QDateTime now = QDateTime::currentDateTime(); update_metrics(true, watts(settings.value(QZSettings::weight, QZSettings::default_weight).toFloat())); @@ -50,8 +51,8 @@ void faketreadmill::update() { cadenceFromAppleWatch(); Distance += ((Speed.value() / (double)3600.0) / - ((double)1000.0 / (double)(lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())))); - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + ((double)1000.0 / (double)(lastRefreshCharacteristicChanged.msecsTo(now)))); + lastRefreshCharacteristicChanged = now; // ******************************************* virtual treadmill init ************************************* if (!firstStateChanged && !this->hasVirtualDevice()) { diff --git a/src/fitplusbike.cpp b/src/fitplusbike.cpp index 77cacf2b4..2b306c452 100644 --- a/src/fitplusbike.cpp +++ b/src/fitplusbike.cpp @@ -376,6 +376,7 @@ void fitplusbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -428,7 +429,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } index += 2; qDebug() << QStringLiteral("Current Speed: ") + QString::number(Speed.value()); @@ -525,7 +526,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -538,7 +539,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte #endif { if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) { - Heart = ((double)((newValue.at(index)))); + Heart = ((double)(((uint8_t)newValue.at(index)))); // index += 1; // NOTE: clang-analyzer-deadcode.DeadStores qDebug() << (QStringLiteral("Current Heart: ") + QString::number(Heart.value())); } else { @@ -597,7 +598,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte else*/ Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } else if (newValue.length() == 13) { @@ -625,7 +626,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte else Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } if (watts()) @@ -634,17 +635,17 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (Cadence.value() > 0) { CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) diff --git a/src/fitshowtreadmill.cpp b/src/fitshowtreadmill.cpp index 6b5645be9..a6dc49933 100644 --- a/src/fitshowtreadmill.cpp +++ b/src/fitshowtreadmill.cpp @@ -158,7 +158,7 @@ void fitshowtreadmill::update() { if (initRequest) { initRequest = false; - btinit((lastSpeed > 0 ? true : false)); + btinit(true); } else if (bluetoothDevice.isValid() && m_control->state() == QLowEnergyController::DiscoveredState && gattCommunicationChannelService && gattWriteCharacteristic.isValid() && gattNotifyCharacteristic.isValid() && initDone) { @@ -220,7 +220,22 @@ void fitshowtreadmill::update() { if (lastSpeed == 0.0) { lastSpeed = 0.5; } - btinit(true); + + uint8_t startTape1[] = { + FITSHOW_SYS_CONTROL, + FITSHOW_CONTROL_READY_OR_START, + (FITSHOW_TREADMILL_SPORT_ID >> 0) & 0xFF, + (FITSHOW_TREADMILL_SPORT_ID >> 8) & 0xFF, + (FITSHOW_TREADMILL_SPORT_ID >> 16) & 0xFF, + (FITSHOW_TREADMILL_SPORT_ID >> 24) & 0xFF, + FITSHOW_SYS_MODE_NORMAL, + 0x00, // number of blocks (u8) + 0x00, + 0x00 // mode-dependent value (u16le) + }; // to verify + scheduleWrite(startTape1, sizeof(startTape1), QStringLiteral("init_start")); + forceSpeedOrIncline(lastSpeed, lastInclination); + lastStart = QDateTime::currentMSecsSinceEpoch(); requestStart = -1; emit tapeStarted(); diff --git a/src/flywheelbike.cpp b/src/flywheelbike.cpp index e461ace45..56959bbbf 100644 --- a/src/flywheelbike.cpp +++ b/src/flywheelbike.cpp @@ -240,6 +240,7 @@ void flywheelbike::updateStats() { } void flywheelbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); static uint8_t zero_fix_filter = 0; // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); @@ -293,7 +294,7 @@ void flywheelbike::characteristicChanged(const QLowEnergyCharacteristic &charact } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } // https://www.facebook.com/groups/149984563348738/permalink/174268944253633/?comment_id=174366620910532&reply_comment_id=174666314213896 diff --git a/src/ftmsbike.cpp b/src/ftmsbike.cpp index 923066d21..4657b1f41 100644 --- a/src/ftmsbike.cpp +++ b/src/ftmsbike.cpp @@ -197,6 +197,7 @@ void ftmsbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -246,7 +247,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } index += 2; emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); @@ -295,7 +296,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris } Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); @@ -367,7 +368,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -438,7 +439,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); index += 2; @@ -461,7 +462,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris index += 3; } else { Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); } emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); @@ -557,7 +558,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -599,7 +600,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (heartRateBeltName.startsWith(QStringLiteral("Disabled")) && (!heart || Heart.value() == 0 || disable_hr_frommachinery)) { diff --git a/src/ftmsrower.cpp b/src/ftmsrower.cpp index c1a6d45f8..7cd114858 100644 --- a/src/ftmsrower.cpp +++ b/src/ftmsrower.cpp @@ -136,6 +136,7 @@ void ftmsrower::serviceDiscovered(const QBluetoothUuid &gatt) { } void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); @@ -185,7 +186,7 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri if (!Flags.moreData) { - if ((WATER_ROWER || DFIT_L_R) && lastStroke.secsTo(QDateTime::currentDateTime()) > 3) { + if ((WATER_ROWER || DFIT_L_R) && lastStroke.secsTo(now) > 3) { qDebug() << "Resetting cadence!"; Cadence = 0; m_watt = 0; @@ -198,7 +199,7 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri (((uint16_t)((uint8_t)newValue.at(index + 2)) << 8) | (uint16_t)((uint8_t)newValue.at(index + 1))); if (lastStrokesCount != StrokesCount.value()) { - lastStroke = QDateTime::currentDateTime(); + lastStroke = now; } lastStrokesCount = StrokesCount.value(); @@ -230,7 +231,7 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri index += 3; } else { Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); } emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); @@ -303,7 +304,7 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -346,7 +347,7 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) { update_hr_from_external(); diff --git a/src/gpx.cpp b/src/gpx.cpp index cd33f7c66..691533c0e 100644 --- a/src/gpx.cpp +++ b/src/gpx.cpp @@ -7,12 +7,16 @@ gpx::gpx(QObject *parent) : QObject(parent) {} -QList gpx::open(const QString &gpx) { +QList gpx::open(const QString &gpx, bluetoothdevice::BLUETOOTH_TYPE device_type) { QSettings settings; const double meter_limit_for_auto_loop = 300; bool treadmill_force_speed = settings.value(QZSettings::treadmill_force_speed, QZSettings::default_treadmill_force_speed).toBool(); bool gpx_loop = settings.value(QZSettings::gpx_loop, QZSettings::default_gpx_loop).toBool(); + + if(device_type == bluetoothdevice::BIKE) + treadmill_force_speed = false; + QFile input(gpx); input.open(QIODevice::ReadOnly); QDomDocument doc; diff --git a/src/gpx.h b/src/gpx.h index 9ed56f7bc..c0c214c06 100644 --- a/src/gpx.h +++ b/src/gpx.h @@ -29,7 +29,7 @@ class gpx : public QObject { Q_OBJECT public: explicit gpx(QObject *parent = nullptr); - QList open(const QString &gpx); + QList open(const QString &gpx, bluetoothdevice::BLUETOOTH_TYPE device_type); static void save(const QString &filename, QList session, bluetoothdevice::BLUETOOTH_TYPE type); QString getVideoURL() {return videoUrl;} diff --git a/src/homeform.cpp b/src/homeform.cpp index fd96b20bb..ccd21a1bf 100644 --- a/src/homeform.cpp +++ b/src/homeform.cpp @@ -5,6 +5,7 @@ #include "localipaddress.h" #ifdef Q_OS_ANDROID #include "keepawakehelper.h" +#include #endif #include "material.h" #include "qfit.h" @@ -52,7 +53,7 @@ using namespace std::chrono_literals; #if defined(WIN32) #pragma message("DEFINE STRAVA_CLIENT_ID!!!") #else -#warning "DEFINE STRAVA_CLIENT_ID!!!" +#pragma message "DEFINE STRAVA_CLIENT_ID!!!" #endif #endif #define _STR(x) #x @@ -474,6 +475,8 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) { QObject::connect(home, SIGNAL(start_clicked()), this, SLOT(Start())); QObject::connect(home, SIGNAL(stop_clicked()), this, SLOT(Stop())); QObject::connect(stack, SIGNAL(trainprogram_open_clicked(QUrl)), this, SLOT(trainprogram_open_clicked(QUrl))); + QObject::connect(stack, SIGNAL(trainprogram_open_other_folder(QUrl)), this, SLOT(trainprogram_open_other_folder(QUrl))); + QObject::connect(stack, SIGNAL(gpx_open_other_folder(QUrl)), this, SLOT(gpx_open_other_folder(QUrl))); QObject::connect(stack, SIGNAL(profile_open_clicked(QUrl)), this, SLOT(profile_open_clicked(QUrl))); QObject::connect(stack, SIGNAL(trainprogram_preview(QUrl)), this, SLOT(trainprogram_preview(QUrl))); QObject::connect(stack, SIGNAL(gpxpreview_open_clicked(QUrl)), this, SLOT(gpxpreview_open_clicked(QUrl))); @@ -500,6 +503,8 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) { QObject::connect(stack, SIGNAL(floatingOpen()), this, SLOT(floatingOpen())); QObject::connect(stack, SIGNAL(openFloatingWindowBrowser()), this, SLOT(openFloatingWindowBrowser())); + qDebug() << "homeform constructor events linked"; + #if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) QObject::connect(engine, &QQmlApplicationEngine::quit, &QGuiApplication::quit); #endif @@ -549,7 +554,8 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) { while (itAndroid.hasNext()) { qDebug() << itAndroid.filePath() << itAndroid.fileName() << itAndroid.filePath().replace(itAndroid.path(), ""); if (!QFile(getWritableAppDir() + itAndroid.next().replace(itAndroid.path(), "")).exists()) { - QFile::copy(itAndroid.filePath(), getWritableAppDir() + itAndroid.filePath().replace(itAndroid.path(), "")); + if(QFile::copy(itAndroid.filePath(), getWritableAppDir() + itAndroid.filePath().replace(itAndroid.path(), ""))) + QFile::remove(itAndroid.filePath()); } } } @@ -649,6 +655,8 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) { }); }); #endif + + bluetoothManager->homeformLoaded = true; } void homeform::setActivityDescription(QString desc) { activityDescription = desc; } @@ -657,8 +665,12 @@ void homeform::chartSaved(QString fileName) { if (!stopped) return; chartImagesFilenames.append(fileName); - if (chartImagesFilenames.length() >= 8) { + if (chartImagesFilenames.length() >= 9) { sendMail(); + qDebug() << "removing chart images"; + for (const QString &f : qAsConst(chartImagesFilenames)) { + QFile::remove(f); + } chartImagesFilenames.clear(); } } @@ -3344,6 +3356,10 @@ void homeform::Stop() { emit startIconChanged(startIcon()); emit startTextChanged(startText()); emit startColorChanged(startColor()); + + // clearing the label on top because if it was running a training program, with stop the program will be terminated + m_info = workoutName(); + emit infoChanged(m_info); } if (trainProgram) { @@ -3769,7 +3785,6 @@ void homeform::update() { speed->setValueFontColor(QStringLiteral("red")); this->pace->setValueFontColor(QStringLiteral("red")); } - bluetoothManager->device()->currentSpeed().setColor(speed->valueFontColor()); } else { if (bluetoothManager->device()->currentSpeed().value() <= trainProgram->currentRow().upper_speed && bluetoothManager->device()->currentSpeed().value() >= trainProgram->currentRow().lower_speed) { @@ -3785,7 +3800,6 @@ void homeform::update() { this->target_zone->setValueFontColor(QStringLiteral("red")); this->pace->setValueFontColor(QStringLiteral("red")); } - bluetoothManager->device()->currentSpeed().setColor(speed->valueFontColor()); } this->target_pace->setValue( @@ -4037,7 +4051,6 @@ void homeform::update() { speed->setValueFontColor(QStringLiteral("red")); this->pace->setValueFontColor(QStringLiteral("red")); } - bluetoothManager->device()->currentSpeed().setColor(speed->valueFontColor()); } } else if (bluetoothManager->device()->deviceType() == bluetoothdevice::ELLIPTICAL) { @@ -4139,10 +4152,6 @@ void homeform::update() { } else { this->peloton_resistance->setValueFontColor(QStringLiteral("orange")); } - if (bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE) - ((bike *)bluetoothManager->device()) - ->pelotonResistance() - .setColor(this->peloton_resistance->valueFontColor()); } int16_t lower_cadence = trainProgram->currentRow().lower_cadence; @@ -4165,7 +4174,6 @@ void homeform::update() { } else { this->cadence->setValueFontColor(QStringLiteral("orange")); } - bluetoothManager->device()->currentCadence().setColor(this->cadence->valueFontColor()); } } @@ -4261,7 +4269,6 @@ void homeform::update() { ftp->setValueFontColor(QStringLiteral("red")); watt->setValueFontColor(QStringLiteral("red")); } - bluetoothManager->device()->wattsMetric().setColor(watt->valueFontColor()); bluetoothManager->device()->setPowerZone(ftpZone); ftp->setValue(QStringLiteral("Z") + QString::number(ftpZone, 'f', 1)); ftp->setSecondLine(ftpMinW + QStringLiteral("-") + ftpMaxW + QStringLiteral("W ") + @@ -4459,7 +4466,6 @@ void homeform::update() { pidHR->setValueFontColor(QStringLiteral("white")); break; } - bluetoothManager->device()->currentHeart().setColor(heart->valueFontColor()); bluetoothManager->device()->setHeartZone(currentHRZone); Z = QStringLiteral("Z") + QString::number(currentHRZone, 'f', 1); heart->setSecondLine(Z + QStringLiteral(" AVG: ") + @@ -4909,6 +4915,16 @@ void homeform::update() { } if (!stopped && !paused) { + if(settings.value(QZSettings::autolap_distance, QZSettings::default_autolap_distance).toDouble() != 0) { + if (bluetoothManager->device()->currentDistance().lapValue() >= + settings.value(QZSettings::autolap_distance, QZSettings::default_autolap_distance).toDouble()) { + qDebug() << QStringLiteral("Autolap based on distance"); + Lap(); + setToastRequested("AutoLap " + QString::number(settings.value(QZSettings::autolap_distance, QZSettings::default_autolap_distance).toDouble(), 'f', 1)); + emit toastRequestedChanged(toastRequested()); + } + } + if (settings.value(QZSettings::tts_enabled, QZSettings::default_tts_enabled).toBool()) { static double tts_speed_played = 0; bool description = @@ -5147,8 +5163,13 @@ void homeform::update() { } } + if(bluetoothManager->device()->currentSpeed().value() > 0 && !isinf(bluetoothManager->device()->currentSpeed().value())) + bluetoothManager->device()->addCurrentDistance1s((bluetoothManager->device()->currentSpeed().value() / 3600.0)); + + qDebug() << "Current Distance 1s:" << bluetoothManager->device()->currentDistance1s().value() << bluetoothManager->device()->currentSpeed().value(); + SessionLine s( - bluetoothManager->device()->currentSpeed().value(), inclination, bluetoothManager->device()->odometer(), + bluetoothManager->device()->currentSpeed().value(), inclination, bluetoothManager->device()->currentDistance1s().value(), watts, resistance, peloton_resistance, (uint8_t)bluetoothManager->device()->currentHeart().value(), pace, cadence, bluetoothManager->device()->calories().value(), bluetoothManager->device()->elevationGain().value(), @@ -5207,30 +5228,78 @@ bool homeform::getLap() { return true; } -void homeform::copyAndroidContentsURI(QFile* file, QString subfolder) { -#ifdef Q_OS_ANDROID - QString filename = file->fileName(); - int substr = filename.lastIndexOf("%2F"); - if(substr) { - filename = filename.mid(substr + 3); +QString homeform::getFileNameFromContentUri(const QString &uriString) { + qDebug() << "getFileNameFromContentUri" << uriString; + if(!uriString.startsWith("content")) { + return uriString; + } +#ifdef Q_OS_ANDROID + + QAndroidJniObject jUriString = QAndroidJniObject::fromString(uriString); + QAndroidJniObject jUri = QAndroidJniObject::callStaticObjectMethod("android/net/Uri", "parse", "(Ljava/lang/String;)Landroid/net/Uri;", jUriString.object()); + QAndroidJniObject result = QAndroidJniObject::callStaticObjectMethod( + "org/cagnulen/qdomyoszwift/ContentHelper", + "getFileName", + "(Landroid/content/Context;Landroid/net/Uri;)Ljava/lang/String;", + QtAndroid::androidContext().object(), + jUri.object()); + return result.toString(); +#else + return uriString; +#endif +} + +QString homeform::copyAndroidContentsURI(QUrl file, QString subfolder) { +#ifdef Q_OS_ANDROID + QString fileNameLocal = ""; + qDebug() << "Android Version:" << QOperatingSystemVersion::current(); + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Android, 13)) + fileNameLocal = getFileNameFromContentUri(file.toString()); + if(fileNameLocal.contains(getWritableAppDir() + subfolder + "/")) { + qDebug() << "no need to copy file, the file is already in QZ subfolder" << file << subfolder; + return file.toString(); + } + + QString filename = ""; + QFile fileFile(QQmlFile::urlToLocalFileOrQrc(file)); + // android <14 fallback + if(fileNameLocal.length() == 0) { + qDebug() << "android <14 fallback" << fileNameLocal << filename << file.fileName(); + filename = file.fileName(); + } else { + QFileInfo f(fileNameLocal); + filename = f.fileName(); } - bool copy = file->copy(getWritableAppDir() + subfolder + "/" + filename); - qDebug() << "copy" << getWritableAppDir() + subfolder + "/" + filename << copy; + QString dest = getWritableAppDir() + subfolder + "/" + filename; + qDebug() << file.fileName() << fileNameLocal << filename; + QFile::remove(dest); + bool copy = fileFile.copy(dest); + qDebug() << "copy" << dest << copy << fileFile.exists() << fileFile.isReadable(); + return dest; #endif + return file.toString(); } void homeform::profile_open_clicked(const QUrl &fileName) { QFile file(QQmlFile::urlToLocalFileOrQrc(fileName)); - copyAndroidContentsURI(&file, "profiles"); + copyAndroidContentsURI(fileName, "profiles"); +} + +void homeform::trainprogram_open_other_folder(const QUrl &fileName) { + QFile file(QQmlFile::urlToLocalFileOrQrc(fileName)); + copyAndroidContentsURI(fileName, "training"); +} + +void homeform::gpx_open_other_folder(const QUrl &fileName) { + QFile file(QQmlFile::urlToLocalFileOrQrc(fileName)); + copyAndroidContentsURI(fileName, "gpx"); } void homeform::trainprogram_open_clicked(const QUrl &fileName) { qDebug() << QStringLiteral("trainprogram_open_clicked") << fileName; QFile file(QQmlFile::urlToLocalFileOrQrc(fileName)); - copyAndroidContentsURI(&file, "training"); - qDebug() << file.fileName(); if (!file.fileName().isEmpty()) { { if (previewTrainProgram) { @@ -5241,7 +5310,7 @@ void homeform::trainprogram_open_clicked(const QUrl &fileName) { delete trainProgram; } - trainProgram = trainprogram::load(file.fileName(), bluetoothManager); + trainProgram = trainprogram::load(file.fileName(), bluetoothManager, file.fileName().right(3).toUpper()); QString movieName = file.fileName().left(file.fileName().length() - 3) + "mp4"; if (QFile::exists(movieName)) { @@ -5258,7 +5327,7 @@ void homeform::trainprogram_open_clicked(const QUrl &fileName) { trainingProgram()->setVideoAvailable(false); } - stravaWorkoutName = QFileInfo(fileName.fileName()).baseName(); + stravaWorkoutName = QFileInfo(file.fileName()).baseName(); stravaPelotonInstructorName = QStringLiteral(""); emit workoutNameChanged(workoutName()); emit instructorNameChanged(instructorName()); @@ -5278,14 +5347,15 @@ void homeform::trainprogram_preview(const QUrl &fileName) { qDebug() << QStringLiteral("trainprogram_preview") << fileName; QFile file(QQmlFile::urlToLocalFileOrQrc(fileName)); - qDebug() << file.fileName(); - if (!file.fileName().isEmpty()) { + QString fileNameLocal = getFileNameFromContentUri(file.fileName()); + qDebug() << fileNameLocal; + if (!fileNameLocal.isEmpty()) { { if (previewTrainProgram) { delete previewTrainProgram; previewTrainProgram = 0; } - previewTrainProgram = trainprogram::load(file.fileName(), bluetoothManager); + previewTrainProgram = trainprogram::load(file.fileName(), bluetoothManager, fileNameLocal.right(3).toUpper()); emit previewWorkoutPointsChanged(preview_workout_points()); emit previewWorkoutDescriptionChanged(previewWorkoutDescription()); emit previewWorkoutTagsChanged(previewWorkoutTags()); @@ -5365,9 +5435,7 @@ void homeform::gpx_open_clicked(const QUrl &fileName) { qDebug() << QStringLiteral("gpx_open_clicked") << fileName; QFile file(QQmlFile::urlToLocalFileOrQrc(fileName)); - copyAndroidContentsURI(&file, "gpx"); - qDebug() << file.fileName(); stravaWorkoutName = QFileInfo(file.fileName()).baseName(); if (!file.fileName().isEmpty()) { { @@ -5379,7 +5447,7 @@ void homeform::gpx_open_clicked(const QUrl &fileName) { // KML to GPX https://www.gpsvisualizer.com/elevation gpx g; QList list; - auto g_list = g.open(file.fileName()); + auto g_list = g.open(file.fileName(), bluetoothManager->device() ? bluetoothManager->device()->deviceType() : bluetoothdevice::BIKE); if (bluetoothManager->device()) bluetoothManager->device()->setGPXFile(file.fileName()); gpx_altitude_point_for_treadmill last; @@ -5449,7 +5517,7 @@ void homeform::gpxpreview_open_clicked(const QUrl &fileName) { if (!file.fileName().isEmpty()) { gpx g; - auto g_list = g.open(file.fileName()); + auto g_list = g.open(file.fileName(), bluetoothManager->device() ? bluetoothManager->device()->deviceType() : bluetoothdevice::BIKE); gpx_preview.clearPath(); for (const auto &p : g_list) { gpx_preview.addCoordinate(QGeoCoordinate(p.latitude, p.longitude, p.elevation)); @@ -5874,7 +5942,7 @@ QOAuth2AuthorizationCodeFlow *homeform::strava_connect() { #elif defined(WIN32) #pragma message("DEFINE STRAVA_SECRET_KEY!!!") #else -#warning "DEFINE STRAVA_SECRET_KEY!!!" +#pragma message "DEFINE STRAVA_SECRET_KEY!!!" #endif strava->setModifyParametersFunction( buildModifyParametersFunction(QUrl(QLatin1String("")), QUrl(QLatin1String("")))); @@ -5995,7 +6063,7 @@ void homeform::sendMail() { SmtpClient smtp(STRINGIFY(SMTP_SERVER), 587, SmtpClient::TlsConnection); connect(&smtp, SIGNAL(smtpError(SmtpClient::SmtpError)), this, SLOT(smtpError(SmtpClient::SmtpError))); #else -#warning "stmp server is unset!" +#pragma message "stmp server is unset!" SmtpClient smtp(QLatin1String(""), 25, SmtpClient::TlsConnection); return; #endif @@ -6007,7 +6075,7 @@ void homeform::sendMail() { #define STRINGIFY(x) _STR(x) smtp.setUser(STRINGIFY(SMTP_USERNAME)); #else -#warning "smtp username is unset!" +#pragma message "smtp username is unset!" return; #endif #ifdef SMTP_PASSWORD @@ -6015,7 +6083,7 @@ void homeform::sendMail() { #define STRINGIFY(x) _STR(x) smtp.setPassword(STRINGIFY(SMTP_PASSWORD)); #else -#warning "smtp password is unset!" +#pragma message "smtp password is unset!" return; #endif @@ -6367,7 +6435,7 @@ void homeform::saveSettings(const QUrl &filename) { void homeform::loadSettings(const QUrl &filename) { QFile file(QQmlFile::urlToLocalFileOrQrc(filename)); - copyAndroidContentsURI(&file, "settings"); + copyAndroidContentsURI(filename, "settings"); qDebug() << "homeform::loadSettings" << file.fileName(); diff --git a/src/homeform.h b/src/homeform.h index e44b07f7f..72587b2d5 100644 --- a/src/homeform.h +++ b/src/homeform.h @@ -199,6 +199,7 @@ class homeform : public QObject { QObject *stack = rootObject; screenCapture s(reinterpret_cast(stack)); s.capture(filenameScreenshot); + chartImagesFilenames.append(filenameScreenshot); } Q_INVOKABLE void save_screenshot_chart(QQuickItem *item, QString filename) { @@ -554,6 +555,68 @@ class homeform : public QObject { QString getStravaAuthUrl() { return stravaAuthUrl; } bool stravaWebVisible() { return stravaAuthWebVisible; } trainprogram *trainingProgram() { return trainProgram; } + + DataObject *speed; + DataObject *inclination; + DataObject *cadence; + DataObject *elevation; + DataObject *calories; + DataObject *odometer; + DataObject *pace; + DataObject *datetime; + DataObject *resistance; + DataObject *watt; + DataObject *avgWatt; + DataObject *avgWattLap; + DataObject *heart; + DataObject *fan; + DataObject *jouls; + DataObject *peloton_offset; + DataObject *peloton_remaining; + DataObject *elapsed; + DataObject *moving_time; + DataObject *peloton_resistance; + DataObject *target_resistance; + DataObject *target_peloton_resistance; + DataObject *target_cadence; + DataObject *target_power; + DataObject *target_zone; + DataObject *target_speed; + DataObject *target_pace; + DataObject *target_incline; + DataObject *ftp; + DataObject *lapElapsed; + DataObject *weightLoss; + DataObject *strokesLength; + DataObject *strokesCount; + DataObject *wattKg; + DataObject *gears; + DataObject *remaningTimeTrainingProgramCurrentRow; + DataObject *nextRows; + DataObject *mets; + DataObject *targetMets; + DataObject *steeringAngle; + DataObject *pidHR; + DataObject *extIncline; + DataObject *instantaneousStrideLengthCM; + DataObject *groundContactMS; + DataObject *verticalOscillationMM; + DataObject *preset_resistance_1; + DataObject *preset_resistance_2; + DataObject *preset_resistance_3; + DataObject *preset_resistance_4; + DataObject *preset_resistance_5; + DataObject *preset_speed_1; + DataObject *preset_speed_2; + DataObject *preset_speed_3; + DataObject *preset_speed_4; + DataObject *preset_speed_5; + DataObject *preset_inclination_1; + DataObject *preset_inclination_2; + DataObject *preset_inclination_3; + DataObject *preset_inclination_4; + DataObject *preset_inclination_5; + DataObject *pace_last500m; private: static homeform *m_singleton; @@ -617,68 +680,6 @@ class homeform : public QObject { bool m_startRequested = false; bool m_overridePower = false; - DataObject *speed; - DataObject *inclination; - DataObject *cadence; - DataObject *elevation; - DataObject *calories; - DataObject *odometer; - DataObject *pace; - DataObject *datetime; - DataObject *resistance; - DataObject *watt; - DataObject *avgWatt; - DataObject *avgWattLap; - DataObject *heart; - DataObject *fan; - DataObject *jouls; - DataObject *peloton_offset; - DataObject *peloton_remaining; - DataObject *elapsed; - DataObject *moving_time; - DataObject *peloton_resistance; - DataObject *target_resistance; - DataObject *target_peloton_resistance; - DataObject *target_cadence; - DataObject *target_power; - DataObject *target_zone; - DataObject *target_speed; - DataObject *target_pace; - DataObject *target_incline; - DataObject *ftp; - DataObject *lapElapsed; - DataObject *weightLoss; - DataObject *strokesLength; - DataObject *strokesCount; - DataObject *wattKg; - DataObject *gears; - DataObject *remaningTimeTrainingProgramCurrentRow; - DataObject *nextRows; - DataObject *mets; - DataObject *targetMets; - DataObject *steeringAngle; - DataObject *pidHR; - DataObject *extIncline; - DataObject *instantaneousStrideLengthCM; - DataObject *groundContactMS; - DataObject *verticalOscillationMM; - DataObject *preset_resistance_1; - DataObject *preset_resistance_2; - DataObject *preset_resistance_3; - DataObject *preset_resistance_4; - DataObject *preset_resistance_5; - DataObject *preset_speed_1; - DataObject *preset_speed_2; - DataObject *preset_speed_3; - DataObject *preset_speed_4; - DataObject *preset_speed_5; - DataObject *preset_inclination_1; - DataObject *preset_inclination_2; - DataObject *preset_inclination_3; - DataObject *preset_inclination_4; - DataObject *preset_inclination_5; - DataObject *pace_last500m; - QTimer *timer; QTimer *backupTimer; @@ -694,7 +695,8 @@ class homeform : public QObject { static quint64 cryptoKeySettingsProfiles(); - static void copyAndroidContentsURI(QFile* file, QString subfolder); + static QString copyAndroidContentsURI(QUrl file, QString subfolder); + static QString getFileNameFromContentUri(const QString &uriString); int16_t fanOverride = 0; @@ -760,6 +762,8 @@ class homeform : public QObject { void deviceConnected(QBluetoothDeviceInfo b); void ftmsAccessoryConnected(smartspin2k *d); void trainprogram_open_clicked(const QUrl &fileName); + void trainprogram_open_other_folder(const QUrl &fileName); + void gpx_open_other_folder(const QUrl &fileName); void profile_open_clicked(const QUrl &fileName); void trainprogram_preview(const QUrl &fileName); void gpxpreview_open_clicked(const QUrl &fileName); diff --git a/src/horizongr7bike.cpp b/src/horizongr7bike.cpp index 00806a947..b55afd86b 100644 --- a/src/horizongr7bike.cpp +++ b/src/horizongr7bike.cpp @@ -144,6 +144,7 @@ void horizongr7bike::serviceDiscovered(const QBluetoothUuid &gatt) { } void horizongr7bike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -195,7 +196,7 @@ void horizongr7bike::characteristicChanged(const QLowEnergyCharacteristic &chara settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 if (!settings.value(QZSettings::speed_power_based, QZSettings::default_speed_power_based).toBool()) { @@ -206,12 +207,12 @@ void horizongr7bike::characteristicChanged(const QLowEnergyCharacteristic &chara } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); return; @@ -231,7 +232,7 @@ void horizongr7bike::characteristicChanged(const QLowEnergyCharacteristic &chara } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } index += 2; emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); @@ -286,13 +287,13 @@ void horizongr7bike::characteristicChanged(const QLowEnergyCharacteristic &chara 1000.0;*/ if (firstPacket) Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); index += 3; } else { if (firstPacket) Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); } emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); @@ -341,7 +342,7 @@ void horizongr7bike::characteristicChanged(const QLowEnergyCharacteristic &chara 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -354,7 +355,7 @@ void horizongr7bike::characteristicChanged(const QLowEnergyCharacteristic &chara #endif { if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) { - Heart = ((double)((newValue.at(index)))); + Heart = ((double)(((uint8_t)newValue.at(index)))); // index += 1; // NOTE: clang-analyzer-deadcode.DeadStores emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); } else { @@ -380,7 +381,7 @@ void horizongr7bike::characteristicChanged(const QLowEnergyCharacteristic &chara LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (heartRateBeltName.startsWith(QStringLiteral("Disabled")) && (!Flags.heartRate || Heart.value() == 0 || disable_hr_frommachinery)) { diff --git a/src/horizontreadmill.cpp b/src/horizontreadmill.cpp index c1b03f68d..e309e9fec 100644 --- a/src/horizontreadmill.cpp +++ b/src/horizontreadmill.cpp @@ -27,10 +27,6 @@ horizontreadmill::horizontreadmill(bool noWriteResistance, bool noHeartService) testProfileCRC(); -#ifdef Q_OS_IOS - QZ_EnableDiscoveryCharsAndDescripttors = true; -#endif - m_watt.setType(metric::METRIC_WATT); Speed.setType(metric::METRIC_SPEED); refresh = new QTimer(this); @@ -840,10 +836,31 @@ void horizontreadmill::update() { .startsWith(QStringLiteral("Disabled"))); update_metrics(!power_sensor, watts(settings.value(QZSettings::weight, QZSettings::default_weight).toFloat())); + if (firstDistanceCalculated) { + QDateTime now = QDateTime::currentDateTime(); + KCal += + ((((0.048 * ((double)watts(settings.value(QZSettings::weight, QZSettings::default_weight).toFloat())) + + 1.19) * + settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / + 200.0) / + (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( + now)))); //(( (0.048* Output in watts +1.19) * body weight in + // kg * 3.5) / 200 ) / 60 + Distance += ((Speed.value() / 3600000.0) * + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); + + lastRefreshCharacteristicChanged = now; + } + // updating the treadmill console every second - if (sec1Update++ == (500 / refresh->interval())) { + if (sec1Update++ == (1000 / refresh->interval())) { sec1Update = 0; + if(trx3500_treadmill) { + uint8_t write[] = {FTMS_START_RESUME}; + writeCharacteristic(gattFTMSService, gattWriteCharControlPointId, write, sizeof(write), + "start simulation", false, false); + } // updateDisplay(elapsed); } @@ -1103,12 +1120,14 @@ void horizontreadmill::forceSpeed(double requestSpeed) { } } else if (gattFTMSService) { // for the Tecnogym Myrun - uint8_t write[] = {FTMS_REQUEST_CONTROL}; - writeCharacteristic(gattFTMSService, gattWriteCharControlPointId, write, sizeof(write), "requestControl", false, - false); - write[0] = {FTMS_START_RESUME}; - writeCharacteristic(gattFTMSService, gattWriteCharControlPointId, write, sizeof(write), "start simulation", - false, false); + if(!anplus_treadmill && !trx3500_treadmill) { + uint8_t write[] = {FTMS_REQUEST_CONTROL}; + writeCharacteristic(gattFTMSService, gattWriteCharControlPointId, write, sizeof(write), "requestControl", false, + false); + write[0] = {FTMS_START_RESUME}; + writeCharacteristic(gattFTMSService, gattWriteCharControlPointId, write, sizeof(write), "start simulation", + false, false); + } uint8_t writeS[] = {FTMS_SET_TARGET_SPEED, 0x00, 0x00}; writeS[1] = ((uint16_t)(requestSpeed * 100)) & 0xFF; @@ -1125,6 +1144,9 @@ void horizontreadmill::forceIncline(double requestIncline) { bool horizon_paragon_x = settings.value(QZSettings::horizon_paragon_x, QZSettings::default_horizon_paragon_x).toBool(); + if(tunturi_t60_treadmill) + Inclination = requestIncline; + if (gattCustomService) { if (!horizon_paragon_x) { messageID++; @@ -1164,12 +1186,14 @@ void horizontreadmill::forceIncline(double requestIncline) { } } else if (gattFTMSService) { // for the Tecnogym Myrun - uint8_t write[] = {FTMS_REQUEST_CONTROL}; - writeCharacteristic(gattFTMSService, gattWriteCharControlPointId, write, sizeof(write), "requestControl", false, - false); - write[0] = {FTMS_START_RESUME}; - writeCharacteristic(gattFTMSService, gattWriteCharControlPointId, write, sizeof(write), "start simulation", - false, false); + if(!anplus_treadmill && !trx3500_treadmill) { + uint8_t write[] = {FTMS_REQUEST_CONTROL}; + writeCharacteristic(gattFTMSService, gattWriteCharControlPointId, write, sizeof(write), "requestControl", false, + false); + write[0] = {FTMS_START_RESUME}; + writeCharacteristic(gattFTMSService, gattWriteCharControlPointId, write, sizeof(write), "start simulation", + false, false); + } uint8_t writeS[] = {FTMS_SET_TARGET_INCLINATION, 0x00, 0x00}; if (kettler_treadmill) { @@ -1287,6 +1311,8 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha QString heartRateBeltName = settings.value(QZSettings::heart_rate_belt_name, QZSettings::default_heart_rate_belt_name).toString(); + QDateTime now = QDateTime::currentDateTime(); + emit debug(QStringLiteral(" << ") + characteristic.uuid().toString() + " " + QString::number(newValue.length()) + " " + newValue.toHex(' ')); @@ -1334,14 +1360,14 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); if (firstDistanceCalculated) Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); distanceEval = true; } else if (characteristic.uuid() == QBluetoothUuid((quint16)0xFFF4) && newValue.length() > 70 && @@ -1361,14 +1387,14 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); if (firstDistanceCalculated) Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); distanceEval = true; } else if (characteristic.uuid() == QBluetoothUuid((quint16)0xFFF4) && newValue.length() == 29 && @@ -1385,14 +1411,14 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); if (firstDistanceCalculated) Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); distanceEval = true; } else if (characteristic.uuid() == QBluetoothUuid((quint16)0xFFF4) && newValue.length() > 10 && @@ -1463,16 +1489,17 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha { if (firstDistanceCalculated) Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); distanceEval = true; } emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); if (Flags.inclination) { - Inclination = ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | - (uint16_t)((uint8_t)newValue.at(index)))) / - 10.0; + if(!tunturi_t60_treadmill) + Inclination = ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | + (uint16_t)((uint8_t)newValue.at(index)))) / + 10.0; index += 4; // the ramo value is useless emit debug(QStringLiteral("Current Inclination: ") + QString::number(Inclination.value())); } @@ -1510,7 +1537,7 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 distanceEval = true; } @@ -1526,7 +1553,7 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha if (Flags.heartRate) { if (index < newValue.length()) { - heart = ((double)((newValue.at(index)))); + heart = ((double)(((uint8_t)newValue.at(index)))); emit debug(QStringLiteral("Current Heart: ") + QString::number(heart)); } else { emit debug(QStringLiteral("Error on parsing heart!")); @@ -1606,7 +1633,7 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha } else { if (firstDistanceCalculated) Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); distanceEval = true; } @@ -1685,7 +1712,7 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 distanceEval = true; } @@ -1699,7 +1726,7 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha #endif { if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) { - Heart = ((double)((newValue.at(index)))); + Heart = ((double)(((uint8_t)newValue.at(index)))); // index += 1; // NOTE: clang-analyzer-deadcode.DeadStores emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); } else { @@ -1740,7 +1767,7 @@ void horizontreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha if (distanceEval) { firstDistanceCalculated = true; - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; } if (m_control->error() != QLowEnergyController::NoError) { @@ -1960,6 +1987,7 @@ void horizontreadmill::deviceDiscovered(const QBluetoothDeviceInfo &device) { // horizon treadmill and F80 treadmill, so if we want to add inclination support we have to separate the 2 // devices // *************************************************************************************************************** + emit debug(QStringLiteral("Found new device: ") + device.name() + QStringLiteral(" (") + device.address().toString() + ')'); { @@ -1971,6 +1999,25 @@ void horizontreadmill::deviceDiscovered(const QBluetoothDeviceInfo &device) { } else if (device.name().toUpper().startsWith(QStringLiteral("KETTLER TREADMILL"))) { kettler_treadmill = true; qDebug() << QStringLiteral("KETTLER TREADMILL workaround ON!"); + } else if (device.name().toUpper().startsWith(QStringLiteral("ANPLUS-"))) { + anplus_treadmill = true; + qDebug() << QStringLiteral("ANPLUS TREADMILL workaround ON!"); + } else if (device.name().toUpper().startsWith(QStringLiteral("TUNTURI T60-"))) { + tunturi_t60_treadmill = true; + qDebug() << QStringLiteral("TUNTURI T60 TREADMILL workaround ON!"); + } + + + if (device.name().toUpper().startsWith(QStringLiteral("TRX3500"))) { + trx3500_treadmill = true; + qDebug() << QStringLiteral("TRX3500 TREADMILL workaround ON!"); +#ifdef Q_OS_IOS + QZ_EnableDiscoveryCharsAndDescripttors = false; +#endif + } else { +#ifdef Q_OS_IOS + QZ_EnableDiscoveryCharsAndDescripttors = true; +#endif } m_control = QLowEnergyController::createCentral(bluetoothDevice, this); @@ -2674,7 +2721,7 @@ void horizontreadmill::testProfileCRC() { } double horizontreadmill::minStepInclination() { - if (kettler_treadmill) + if (kettler_treadmill || trx3500_treadmill) return 1.0; else return 0.5; diff --git a/src/horizontreadmill.h b/src/horizontreadmill.h index 1ec9664c3..dd1a26de0 100644 --- a/src/horizontreadmill.h +++ b/src/horizontreadmill.h @@ -88,6 +88,9 @@ class horizontreadmill : public treadmill { bool mobvoi_treadmill = false; bool kettler_treadmill = false; + bool anplus_treadmill = false; + bool tunturi_t60_treadmill = false; + bool trx3500_treadmill = false; void testProfileCRC(); void updateProfileCRC(); diff --git a/src/inner_templates/chartjs/dochart.js b/src/inner_templates/chartjs/dochart.js index beb922c88..fa475824d 100644 --- a/src/inner_templates/chartjs/dochart.js +++ b/src/inner_templates/chartjs/dochart.js @@ -177,7 +177,7 @@ function process_arr(arr) { $('.summary_watts_avg').text(Math.floor(watts_avg) + ' W'); $('.summary_jouls').text(Math.floor(jouls / 1000.0) + ' kJ'); $('.summary_calories').text(Math.floor(calories) + ' kcal'); - $('.summary_distance').text(Math.floor(distance * miles) + (miles === 1 ? ' km' : ' mi')); + $('.summary_distance').text((distance * miles).toFixed(1) + (miles === 1 ? ' km' : ' mi')); $('.summary_cadence_avg').text(Math.floor(cadence_avg) + ' rpm'); $('.summary_resistance_avg').text(Math.floor(peloton_resistance_avg) + ' lvl'); diff --git a/src/inner_templates/floating/floating.htm b/src/inner_templates/floating/floating.htm index b6f3e3599..a6723a616 100644 --- a/src/inner_templates/floating/floating.htm +++ b/src/inner_templates/floating/floating.htm @@ -590,11 +590,11 @@

Peloton Workout in progress! keys_arr = ['speed', 'speed_lapavg', 'cadence', 'cadence_lapavg', 'heart', 'heart_lapavg', 'calories', 'distance', 'watts', 'watts_lapavg', 'elapsed_h', 'elapsed_m', 'elapsed_s', 'resistance', 'resistance_lapavg', 'peloton_resistance', 'peloton_resistance_lapavg', 'speed_lapmax', 'cadence_lapmax', 'heart_lapmax', 'watts_lapmax', 'resistance_lapmax', 'peloton_resistance_lapmax', - 'speed_color', 'cadence_color', 'heart_color', 'watts_color', 'peloton_resistance_color', 'target_resistance', 'target_peloton_resistance', + 'speed_color', 'power_zone_color', 'cadence_color', 'heart_color', 'watts_color', 'peloton_resistance_color', 'target_resistance', 'target_peloton_resistance', 'target_cadence', 'target_power', 'peloton_offset', 'peloton_ask_start', 'target_speed', 'target_pace', 'inclination', 'inclination_lapavg', 'inclination_lapmax', 'target_inclination', 'power_zone', 'power_zone_lapavg', 'power_zone_lapmax', 'target_power_zone', 'jouls', 'row_remaining_time_s', 'row_remaining_time_m', 'row_remaining_time_h' , 'autoresistance', 'gears', 'elevation', 'pace_s' , 'pace_m', - 'avgpace_s', 'avgpace_m', 'maxpace_s' , 'maxpace_m',] + 'avgpace_s', 'avgpace_m', 'maxpace_s' , 'maxpace_m', 'remaining_time_s', 'remaining_time_m', 'remaining_time_h'] let ell = new MainWSQueueElement(null, function (msg) { if (msg.msg === 'workout') { var speed = 0; @@ -628,6 +628,9 @@

Peloton Workout in progress! var row_remaining_time_s = 0; var row_remaining_time_m = 0; var row_remaining_time_h = 0; + var remaining_time_s = 0; + var remaining_time_m = 0; + var remaining_time_h = 0; var resistance = 0; var resistance_lapavg = 0; var peloton_resistance = 0; @@ -721,6 +724,12 @@

Peloton Workout in progress! row_remaining_time_m = msg.content[key]; } else if (key === 'row_remaining_time_s') { row_remaining_time_s = msg.content[key]; + } else if (key === 'remaining_time_h') { + remaining_time_h = msg.content[key]; + } else if (key === 'remaining_time_m') { + remaining_time_m = msg.content[key]; + } else if (key === 'remaining_time_s') { + remaining_time_s = msg.content[key]; } else if (key === 'target_pace_h') { target_pace_h = msg.content[key]; } else if (key === 'target_pace_m') { @@ -758,7 +767,7 @@

Peloton Workout in progress! } else if (key === 'gears') { gears = msg.content[key]; } else if (key === 'peloton_resistance_color') { - $('.peloton_resistance-value').css('color', msg.content[key]); + $('.pelotonresistance-value').css('color', msg.content[key]); } else if (key === 'heart_color') { $('.heart-value').css('color', msg.content[key]); } else if (key === 'cadence_color') { @@ -767,6 +776,8 @@

Peloton Workout in progress! $('.watt-value').css('color', msg.content[key]); } else if (key === 'speed_color') { $('.speed-value').css('color', msg.content[key]); + } else if (key === 'power_zone_color') { + $('.powerzone-value').css('color', msg.content[key]); } else if (key === 'peloton_ask_start' && !peloton_ask_already_running && (msg.content[key] === true || msg.content[key] === 'true')) { peloton_ask_already_running = true; document.getElementById("overlay").hidden = false; @@ -822,7 +833,7 @@

Peloton Workout in progress! $('.pelotonresistance-max').html(peloton_resistance_lapmax.toFixed(0)); $('.distance-value').html("" + odometer.toFixed(2) + ""); $('.rowremainingtime-value').html("" + row_remaining_time_h.toString().padStart(2, "0") + ":" + row_remaining_time_m.toString().padStart(2, "0") + ":" + row_remaining_time_s.toString().padStart(2, "0") + ""); - $('.elapsed-value').html("" + elapsed_h.toString().padStart(2, "0") + ":" + elapsed_m.toString().padStart(2, "0") + ":" + elapsed_s.toString().padStart(2, "0") + ""); + $('.elapsed-value').html("" + elapsed_h.toString().padStart(2, "0") + ":" + elapsed_m.toString().padStart(2, "0") + ":" + elapsed_s.toString().padStart(2, "0") + "" + (remaining_time_h > 0 || remaining_time_m > 0 || remaining_time_s > 0 ? " / " + "" + remaining_time_h.toString().padStart(2, "0") + ":" + remaining_time_m.toString().padStart(2, "0") + ":" + remaining_time_s.toString().padStart(2, "0") + "" : "")); $('.gears-value').html("" + gears.toFixed(0) + ""); if(pace_s.toString() === "-1" || (pace_s.toString() === "0" && pace_m.toString() === "0")) $('.pace-value').html("N/A"); diff --git a/src/inspirebike.cpp b/src/inspirebike.cpp index 52c1fec51..706c80695 100644 --- a/src/inspirebike.cpp +++ b/src/inspirebike.cpp @@ -127,6 +127,7 @@ void inspirebike::serviceDiscovered(const QBluetoothUuid &gatt) { } void inspirebike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -151,17 +152,17 @@ void inspirebike::characteristicChanged(const QLowEnergyCharacteristic &characte if (!settings.value(QZSettings::speed_power_based, QZSettings::default_speed_power_based).toBool()) { Speed = 0.37497622 * ((double)Cadence.value()); } else { - Speed = metric::calculateSpeedFromPower(watts(), Inclination.value(), Speed.value(),fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + Speed = metric::calculateSpeedFromPower(watts(), Inclination.value(), Speed.value(),fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } if (watts()) KCal += ((((0.048 * ((double)watts()) + 1.19) * settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (settings.value(QZSettings::inspire_peloton_formula2, QZSettings::default_inspire_peloton_formula2).toBool()) { // y = 0,0002x^3 - 0.1478x^2 + 4.2412x + 1.8102 @@ -184,7 +185,7 @@ void inspirebike::characteristicChanged(const QLowEnergyCharacteristic &characte LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) diff --git a/src/ios/AppDelegate.swift b/src/ios/AppDelegate.swift index 7e7420364..651f3248c 100644 --- a/src/ios/AppDelegate.swift +++ b/src/ios/AppDelegate.swift @@ -17,9 +17,11 @@ var pedometer = CMPedometer() @objc public class healthkit:NSObject { let w = watchAppStart() + let SwiftDebug = swiftDebug() @objc public func request() { + SwiftDebug.qtDebug("swift debug test") if #available(iOS 13.0, *) { Client.client.start() } else { diff --git a/src/ios/GarminConnect.swift b/src/ios/GarminConnect.swift index 76b0272aa..eedf5de4a 100644 --- a/src/ios/GarminConnect.swift +++ b/src/ios/GarminConnect.swift @@ -45,6 +45,8 @@ class GarminConnectSwift: NSObject, IQDeviceEventDelegate, IQAppMessageDelegate public var HR: Int = 0 public var FootCad: Int = 0 + + let SwiftDebug = swiftDebug() private let formatter: NumberFormatter = { let formatter = NumberFormatter() @@ -65,6 +67,7 @@ class GarminConnectSwift: NSObject, IQDeviceEventDelegate, IQAppMessageDelegate guard url.scheme == GarminConnectSwift.urlScheme, let devices = ConnectIQ.shared?.parseDeviceSelectionResponse(from: url) as? [IQDevice] else { return false } registerForDeviceEvents(devices: devices) + SwiftDebug.qtDebug("GarminConnect: urlParser: return true") return true } @@ -75,6 +78,7 @@ class GarminConnectSwift: NSObject, IQDeviceEventDelegate, IQAppMessageDelegate } public func deviceStatusChanged(_ device: IQDevice!, status: IQDeviceStatus) { + let descriptionStatus: String switch status { case .connected: // The `store` is not necessary for sending messages, I suppose it's for when you want the user to download the app. @@ -82,6 +86,7 @@ class GarminConnectSwift: NSObject, IQDeviceEventDelegate, IQAppMessageDelegate let app = IQApp(uuid: GarminConnectSwift.watchAppUuid, store: nil, device: device) apps[device.uuid] = app print(device.uuid) + descriptionStatus = "connected" ConnectIQ.shared?.register(forAppMessages: app, delegate: self) @@ -93,15 +98,20 @@ class GarminConnectSwift: NSObject, IQDeviceEventDelegate, IQAppMessageDelegate case .bluetoothNotReady, .invalidDevice, .notConnected, .notFound: print(device.uuid) + descriptionStatus = "invalidDevice" apps.removeValue(forKey: device.uuid) @unknown default: + descriptionStatus = "case not handled" print("New case, still unhandled. \(status.rawValue)") } + + SwiftDebug.qtDebug("GarminConnect: deviceStatusChanged: status " + descriptionStatus + " " + device.uuid.uuidString) } func receivedMessage(_ message: Any!, from app: IQApp!) { print("Received message from ConnectIQ: \(message.debugDescription)") + SwiftDebug.qtDebug("GarminConnect: receivedMessage: " + message.debugDescription) guard let array = message as? [Any] else { print("Failed to parse message sent from ConnectIQ.") diff --git a/src/ios/ios_eliteariafan.h b/src/ios/ios_eliteariafan.h new file mode 100644 index 000000000..0684e9aa0 --- /dev/null +++ b/src/ios/ios_eliteariafan.h @@ -0,0 +1,20 @@ +#ifndef IOSELITEARIAFAN_H +#define IOSELITEARIAFAN_H + +#import +#import + +@interface ios_eliteariafan : NSObject + +@property (strong, nonatomic) CBCentralManager *centralManager; +@property (strong, nonatomic) CBPeripheral *connectedPeripheral; +@property (strong, nonatomic) NSString *targetDeviceName; +@property (strong, nonatomic) CBCharacteristic *characteristicUUID1; +@property (strong, nonatomic) CBCharacteristic *characteristicUUID2; + +- (instancetype)init; +- (void)fanSpeedRequest:(uint8_t)speed; + +@end + +#endif // IOSELITEARIAFAN_H diff --git a/src/ios/ios_eliteariafan.mm b/src/ios/ios_eliteariafan.mm new file mode 100644 index 000000000..d6ccd77cf --- /dev/null +++ b/src/ios/ios_eliteariafan.mm @@ -0,0 +1,91 @@ +#import +#import "ios_eliteariafan.h" + +@implementation ios_eliteariafan + +- (instancetype)init { + self = [super init]; + if (self) { + _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; + _targetDeviceName = @"ARIA"; // Nome del dispositivo Bluetooth + } + return self; +} + +- (void)centralManagerDidUpdateState:(CBCentralManager *)central { + if (central.state == CBManagerStatePoweredOn) { + [self.centralManager scanForPeripheralsWithServices:nil options:nil]; + } +} + +- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { + if ([peripheral.name isEqualToString:self.targetDeviceName]) { + self.connectedPeripheral = peripheral; + [self.centralManager stopScan]; + [self.centralManager connectPeripheral:peripheral options:nil]; + } +} + +- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral { + peripheral.delegate = self; + [peripheral discoverServices:nil]; +} + +- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error { + NSLog(@"Peripheral disconnected: %@. Error: %@", peripheral, error); + if ([peripheral.name isEqualToString:self.targetDeviceName]) { + NSLog(@"Attempting to reconnect to %@", self.targetDeviceName); + [self.centralManager connectPeripheral:peripheral options:nil]; + } +} + +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error { + for (CBService *service in peripheral.services) { + [peripheral discoverCharacteristics:nil forService:service]; + } +} + +- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { + CBUUID *uuid1 = [CBUUID UUIDWithString:@"347b0012-7635-408b-8918-8ff3949ce592"]; + CBUUID *uuid2 = [CBUUID UUIDWithString:@"347b0040-7635-408b-8918-8ff3949ce592"]; + + for (CBCharacteristic *characteristic in service.characteristics) { + if ([characteristic.UUID isEqual:uuid1]) { + self.characteristicUUID1 = characteristic; + } else if ([characteristic.UUID isEqual:uuid2]) { + self.characteristicUUID2 = characteristic; + } + } + + // Verifica se entrambe le caratteristiche sono state trovate + if (self.characteristicUUID1 && self.characteristicUUID2) { + // Invia init1 + uint8_t init1[] = {0x02, 0x00, 0x00, 0x3d, 0x00}; + NSData *dataToSend1 = [NSData dataWithBytes:init1 length:sizeof(init1)]; + [peripheral writeValue:dataToSend1 forCharacteristic:self.characteristicUUID1 type:CBCharacteristicWriteWithResponse]; + + // Invia init2 + uint8_t init2[] = {0x05, 0x00}; + NSData *dataToSend2 = [NSData dataWithBytes:init2 length:sizeof(init2)]; + [peripheral writeValue:dataToSend2 forCharacteristic:self.characteristicUUID2 type:CBCharacteristicWriteWithResponse]; + + [self fanSpeedRequest:0]; + } +} + +- (void)fanSpeedRequest:(uint8_t)speed { + if (self.connectedPeripheral.state != CBPeripheralStateConnected) { + NSLog(@"Cannot send fan speed request: Peripheral is not connected."); + return; + } + + uint8_t init10[] = {0x03, 0x01, 0x0e}; + init10[2] = speed; + NSData *dataToSend = [NSData dataWithBytes:init10 length:sizeof(init10)]; + + if (self.characteristicUUID2) { + [self.connectedPeripheral writeValue:dataToSend forCharacteristic:self.characteristicUUID2 type:CBCharacteristicWriteWithResponse]; + } +} + +@end diff --git a/src/ios/lockscreen.h b/src/ios/lockscreen.h index 9222a8c2d..8b8dc9466 100644 --- a/src/ios/lockscreen.h +++ b/src/ios/lockscreen.h @@ -18,7 +18,7 @@ class lockscreen { void virtualbike_setHeartRate(unsigned char heartRate); void virtualbike_setCadence(unsigned short crankRevolutions, unsigned short lastCrankEventTime); - void virtualbike_zwift_ios(bool disable_hr); + void virtualbike_zwift_ios(bool disable_hr, bool garmin_bluetooth_compatibility); double virtualbike_getCurrentSlope(); double virtualbike_getCurrentCRR(); double virtualbike_getCurrentCW(); @@ -46,7 +46,7 @@ class lockscreen { double virtualtreadmill_getPowerRequested(); bool virtualtreadmill_updateFTMS(unsigned short normalizeSpeed, unsigned char currentResistance, unsigned short currentCadence, unsigned short currentWatt, - unsigned short currentInclination); + unsigned short currentInclination, unsigned long long currentDistance); // volume double getVolume(); @@ -63,6 +63,17 @@ class lockscreen { //adb void adb_connect(const char* IP); void adb_sendcommand(const char* command); + + // Elite Aria Fan + void eliteAriaFan(); + void eliteAriaFan_fanSpeedRequest(unsigned char speed); + + // Zwift API + void zwift_api_decodemessage_player(const char* data, int len); + float zwift_api_getaltitude(); + int zwift_api_getdistance(); + float zwift_api_getlatitude(); + float zwift_api_getlongitude(); }; #endif // LOCKSCREEN_H diff --git a/src/ios/lockscreen.mm b/src/ios/lockscreen.mm index da616415d..19894b11c 100644 --- a/src/ios/lockscreen.mm +++ b/src/ios/lockscreen.mm @@ -9,6 +9,7 @@ #include "ios/lockscreen.h" #include #include "ios/AdbClient.h" +#include "ios/ios_eliteariafan.h" @class virtualbike_ios_swift; @class virtualbike_zwift; @@ -26,6 +27,10 @@ static AdbClient *_adb = 0; +static ios_eliteariafan* ios_eliteAriaFan = nil; + +static zwift_protobuf_layer* zwiftProtobufLayer = nil; + void lockscreen::setTimerDisabled() { [[UIApplication sharedApplication] setIdleTimerDisabled: YES]; } @@ -34,6 +39,7 @@ { h = [[healthkit alloc] init]; [h request]; + zwiftProtobufLayer = [[zwift_protobuf_layer alloc] init]; if (@available(iOS 13, *)) { Garmin = [[GarminConnect alloc] init]; } @@ -96,9 +102,9 @@ [_virtualbike updateCadenceWithCrankRevolutions:crankRevolutions LastCrankEventTime:lastCrankEventTime]; } -void lockscreen::virtualbike_zwift_ios(bool disable_hr) +void lockscreen::virtualbike_zwift_ios(bool disable_hr, bool garmin_bluetooth_compatibility) { - _virtualbike_zwift = [[virtualbike_zwift alloc] initWithDisable_hr: disable_hr]; + _virtualbike_zwift = [[virtualbike_zwift alloc] initWithDisable_hr:disable_hr garmin_bluetooth_compatibility:garmin_bluetooth_compatibility]; } void lockscreen::virtualrower_ios() @@ -202,10 +208,10 @@ return 0; } -bool lockscreen::virtualtreadmill_updateFTMS(UInt16 normalizeSpeed, UInt8 currentResistance, UInt16 currentCadence, UInt16 currentWatt, UInt16 currentInclination) +bool lockscreen::virtualtreadmill_updateFTMS(UInt16 normalizeSpeed, UInt8 currentResistance, UInt16 currentCadence, UInt16 currentWatt, UInt16 currentInclination, UInt64 currentDistance) { if(_virtualtreadmill_zwift != nil) - return [_virtualtreadmill_zwift updateFTMSWithNormalizeSpeed:normalizeSpeed currentCadence:currentCadence currentResistance:currentResistance currentWatt:currentWatt currentInclination:currentInclination]; + return [_virtualtreadmill_zwift updateFTMSWithNormalizeSpeed:normalizeSpeed currentCadence:currentCadence currentResistance:currentResistance currentWatt:currentWatt currentInclination:currentInclination currentDistance:currentDistance]; return 0; } @@ -285,4 +291,35 @@ }]; } + +void lockscreen::eliteAriaFan() { + ios_eliteAriaFan = [[ios_eliteariafan alloc] init]; +} + +void lockscreen::eliteAriaFan_fanSpeedRequest(unsigned char speed) { + if(ios_eliteAriaFan) { + [ios_eliteAriaFan fanSpeedRequest:speed]; + } +} + +void lockscreen::zwift_api_decodemessage_player(const char* data, int len) { + NSData *d = [NSData dataWithBytes:data length:len]; + [zwiftProtobufLayer getPlayerStateWithValue:d]; +} + +float lockscreen::zwift_api_getaltitude() { + return [zwiftProtobufLayer getAltitude]; +} + +int lockscreen::zwift_api_getdistance() { + return [zwiftProtobufLayer getDistance]; +} + +float lockscreen::zwift_api_getlatitude() { + return [zwiftProtobufLayer getLatitude]; +} + +float lockscreen::zwift_api_getlongitude() { + return [zwiftProtobufLayer getLongitude]; +} #endif diff --git a/src/ios/swiftDebug.h b/src/ios/swiftDebug.h new file mode 100644 index 000000000..a53939e58 --- /dev/null +++ b/src/ios/swiftDebug.h @@ -0,0 +1,20 @@ +// +// swiftDebug.h +// qdomyoszwift +// +// Created by Roberto Viola on 14/12/23. +// + +#ifndef swiftDebug_h +#define swiftDebug_h + +#import + + +@interface swiftDebug : NSObject + +- (void)qtDebug:(NSString *)inputString;; + +@end + +#endif /* swiftDebug_h */ diff --git a/src/ios/swiftDebug.mm b/src/ios/swiftDebug.mm new file mode 100644 index 000000000..1c8db0e08 --- /dev/null +++ b/src/ios/swiftDebug.mm @@ -0,0 +1,16 @@ +// +// swiftDebug.m +// qdomyoszwift +// +// Created by Roberto Viola on 14/12/23. +// +#import "swiftDebug.h" +#include + +@implementation swiftDebug + +- (void)qtDebug:(NSString *)inputString { + qDebug() << inputString; +} + +@end diff --git a/src/ios/virtualbike_zwift.swift b/src/ios/virtualbike_zwift.swift index 9ca88f1b3..7315efdc6 100644 --- a/src/ios/virtualbike_zwift.swift +++ b/src/ios/virtualbike_zwift.swift @@ -11,9 +11,9 @@ let TrainingStatusUuid = CBUUID(string: "0x2AD3"); @objc public class virtualbike_zwift: NSObject { private var peripheralManager: BLEPeripheralManagerZwift! - @objc public init(disable_hr: Bool) { + @objc public init(disable_hr: Bool, garmin_bluetooth_compatibility: Bool) { super.init() - peripheralManager = BLEPeripheralManagerZwift(disable_hr: disable_hr) + peripheralManager = BLEPeripheralManagerZwift(disable_hr: disable_hr, garmin_bluetooth_compatibility: garmin_bluetooth_compatibility) } @objc public func updateHeartRate(HeartRate: UInt8) @@ -61,6 +61,7 @@ let TrainingStatusUuid = CBUUID(string: "0x2AD3"); } class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { + private var garmin_bluetooth_compatibility: Bool = false private var disable_hr: Bool = false private var peripheralManager: CBPeripheralManager! @@ -108,9 +109,11 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { private var notificationTimer: Timer! = nil //var delegate: BLEPeripheralManagerDelegate? - init(disable_hr: Bool) { + init(disable_hr: Bool, garmin_bluetooth_compatibility: Bool) { super.init() self.disable_hr = disable_hr + self.garmin_bluetooth_compatibility = garmin_bluetooth_compatibility + peripheralManager = CBPeripheralManager(delegate: self, queue: nil) } @@ -119,107 +122,107 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { case .poweredOn: print("Peripheral manager is up and running") - - self.heartRateService = CBMutableService(type: heartRateServiceUUID, primary: true) - let characteristicProperties: CBCharacteristicProperties = [.notify, .read, .write] - let characteristicPermissions: CBAttributePermissions = [.readable] - self.heartRateCharacteristic = CBMutableCharacteristic(type: heartRateCharacteristicUUID, - properties: characteristicProperties, - value: nil, - permissions: characteristicPermissions) - - heartRateService.characteristics = [heartRateCharacteristic] - self.peripheralManager.add(heartRateService) - - self.FitnessMachineService = CBMutableService(type: FitnessMachineServiceUuid, primary: true) - - let FitnessMachineFeatureProperties: CBCharacteristicProperties = [.read] - let FitnessMachineFeaturePermissions: CBAttributePermissions = [.readable] - self.FitnessMachineFeatureCharacteristic = CBMutableCharacteristic(type: FitnessMachineFeatureCharacteristicUuid, - properties: FitnessMachineFeatureProperties, - value: Data (bytes: [0x83, 0x14, 0x00, 0x00, 0x0c, 0xe0, 0x00, 0x00]), - permissions: FitnessMachineFeaturePermissions) - - let supported_resistance_level_rangeProperties: CBCharacteristicProperties = [.read] - let supported_resistance_level_rangePermissions: CBAttributePermissions = [.readable] - self.supported_resistance_level_rangeCharacteristic = CBMutableCharacteristic(type: supported_resistance_level_rangeCharacteristicUuid, - properties: supported_resistance_level_rangeProperties, - value: Data (bytes: [0x0A, 0x00, 0x96, 0x00, 0x0A, 0x00]), - permissions: supported_resistance_level_rangePermissions) - - let FitnessMachineControlPointProperties: CBCharacteristicProperties = [.indicate, .notify, .write] - let FitnessMachineControlPointPermissions: CBAttributePermissions = [.writeable] - self.FitnessMachineControlPointCharacteristic = CBMutableCharacteristic(type: FitnessMachineControlPointUuid, - properties: FitnessMachineControlPointProperties, - value: nil, - permissions: FitnessMachineControlPointPermissions) - - let indoorbikeProperties: CBCharacteristicProperties = [.notify, .read] - let indoorbikePermissions: CBAttributePermissions = [.readable] - self.indoorbikeCharacteristic = CBMutableCharacteristic(type: indoorbikeUuid, - properties: indoorbikeProperties, - value: nil, - permissions: indoorbikePermissions) - - let FitnessMachinestatusProperties: CBCharacteristicProperties = [.notify] - let FitnessMachinestatusPermissions: CBAttributePermissions = [.readable] - self.FitnessMachinestatusCharacteristic = CBMutableCharacteristic(type: FitnessMachinestatusUuid, - properties: FitnessMachinestatusProperties, - value: nil, - permissions: FitnessMachinestatusPermissions) - - let TrainingStatusProperties: CBCharacteristicProperties = [.read] - let TrainingStatusPermissions: CBAttributePermissions = [.readable] - self.TrainingStatusCharacteristic = CBMutableCharacteristic(type: TrainingStatusUuid, - properties: TrainingStatusProperties, - value: Data (bytes: [0x00, 0x01]), - permissions: TrainingStatusPermissions) - - FitnessMachineService.characteristics = [FitnessMachineFeatureCharacteristic, - supported_resistance_level_rangeCharacteristic, - FitnessMachineControlPointCharacteristic, - indoorbikeCharacteristic, - FitnessMachinestatusCharacteristic, - TrainingStatusCharacteristic ] - - self.peripheralManager.add(FitnessMachineService) - - self.CSCService = CBMutableService(type: CSCServiceUUID, primary: true) - - let CSCFeatureProperties: CBCharacteristicProperties = [.read] - let CSCFeaturePermissions: CBAttributePermissions = [.readable] - self.CSCFeatureCharacteristic = CBMutableCharacteristic(type: CSCFeatureCharacteristicUUID, - properties: CSCFeatureProperties, - value: Data (bytes: [0x02, 0x00]), - permissions: CSCFeaturePermissions) - - let SensorLocationProperties: CBCharacteristicProperties = [.read] - let SensorLocationPermissions: CBAttributePermissions = [.readable] - self.SensorLocationCharacteristic = CBMutableCharacteristic(type: SensorLocationCharacteristicUUID, - properties: SensorLocationProperties, - value: Data (bytes: [0x13]), - permissions: SensorLocationPermissions) - - let CSCMeasurementProperties: CBCharacteristicProperties = [.notify, .read] - let CSCMeasurementPermissions: CBAttributePermissions = [.readable] - self.CSCMeasurementCharacteristic = CBMutableCharacteristic(type: CSCMeasurementCharacteristicUUID, - properties: CSCMeasurementProperties, + if(!self.garmin_bluetooth_compatibility) { + self.heartRateService = CBMutableService(type: heartRateServiceUUID, primary: true) + let characteristicProperties: CBCharacteristicProperties = [.notify, .read, .write] + let characteristicPermissions: CBAttributePermissions = [.readable] + self.heartRateCharacteristic = CBMutableCharacteristic(type: heartRateCharacteristicUUID, + properties: characteristicProperties, value: nil, - permissions: CSCMeasurementPermissions) - - let SCControlPointProperties: CBCharacteristicProperties = [.indicate, .write] - let SCControlPointPermissions: CBAttributePermissions = [.writeable] - self.SCControlPointCharacteristic = CBMutableCharacteristic(type: SCControlPointCharacteristicUUID, - properties: SCControlPointProperties, - value: nil, - permissions: SCControlPointPermissions) - - CSCService.characteristics = [CSCFeatureCharacteristic, - SensorLocationCharacteristic, - CSCMeasurementCharacteristic, - SCControlPointCharacteristic] - self.peripheralManager.add(CSCService) - + permissions: characteristicPermissions) + + heartRateService.characteristics = [heartRateCharacteristic] + self.peripheralManager.add(heartRateService) + + self.FitnessMachineService = CBMutableService(type: FitnessMachineServiceUuid, primary: true) + + let FitnessMachineFeatureProperties: CBCharacteristicProperties = [.read] + let FitnessMachineFeaturePermissions: CBAttributePermissions = [.readable] + self.FitnessMachineFeatureCharacteristic = CBMutableCharacteristic(type: FitnessMachineFeatureCharacteristicUuid, + properties: FitnessMachineFeatureProperties, + value: Data (bytes: [0x83, 0x14, 0x00, 0x00, 0x0c, 0xe0, 0x00, 0x00]), + permissions: FitnessMachineFeaturePermissions) + + let supported_resistance_level_rangeProperties: CBCharacteristicProperties = [.read] + let supported_resistance_level_rangePermissions: CBAttributePermissions = [.readable] + self.supported_resistance_level_rangeCharacteristic = CBMutableCharacteristic(type: supported_resistance_level_rangeCharacteristicUuid, + properties: supported_resistance_level_rangeProperties, + value: Data (bytes: [0x0A, 0x00, 0x96, 0x00, 0x0A, 0x00]), + permissions: supported_resistance_level_rangePermissions) + + let FitnessMachineControlPointProperties: CBCharacteristicProperties = [.indicate, .notify, .write] + let FitnessMachineControlPointPermissions: CBAttributePermissions = [.writeable] + self.FitnessMachineControlPointCharacteristic = CBMutableCharacteristic(type: FitnessMachineControlPointUuid, + properties: FitnessMachineControlPointProperties, + value: nil, + permissions: FitnessMachineControlPointPermissions) + + let indoorbikeProperties: CBCharacteristicProperties = [.notify, .read] + let indoorbikePermissions: CBAttributePermissions = [.readable] + self.indoorbikeCharacteristic = CBMutableCharacteristic(type: indoorbikeUuid, + properties: indoorbikeProperties, + value: nil, + permissions: indoorbikePermissions) + + let FitnessMachinestatusProperties: CBCharacteristicProperties = [.notify] + let FitnessMachinestatusPermissions: CBAttributePermissions = [.readable] + self.FitnessMachinestatusCharacteristic = CBMutableCharacteristic(type: FitnessMachinestatusUuid, + properties: FitnessMachinestatusProperties, + value: nil, + permissions: FitnessMachinestatusPermissions) + + let TrainingStatusProperties: CBCharacteristicProperties = [.read] + let TrainingStatusPermissions: CBAttributePermissions = [.readable] + self.TrainingStatusCharacteristic = CBMutableCharacteristic(type: TrainingStatusUuid, + properties: TrainingStatusProperties, + value: Data (bytes: [0x00, 0x01]), + permissions: TrainingStatusPermissions) + + FitnessMachineService.characteristics = [FitnessMachineFeatureCharacteristic, + supported_resistance_level_rangeCharacteristic, + FitnessMachineControlPointCharacteristic, + indoorbikeCharacteristic, + FitnessMachinestatusCharacteristic, + TrainingStatusCharacteristic ] + + self.peripheralManager.add(FitnessMachineService) + + self.CSCService = CBMutableService(type: CSCServiceUUID, primary: true) + + let CSCFeatureProperties: CBCharacteristicProperties = [.read] + let CSCFeaturePermissions: CBAttributePermissions = [.readable] + self.CSCFeatureCharacteristic = CBMutableCharacteristic(type: CSCFeatureCharacteristicUUID, + properties: CSCFeatureProperties, + value: Data (bytes: [0x02, 0x00]), + permissions: CSCFeaturePermissions) + + let SensorLocationProperties: CBCharacteristicProperties = [.read] + let SensorLocationPermissions: CBAttributePermissions = [.readable] + self.SensorLocationCharacteristic = CBMutableCharacteristic(type: SensorLocationCharacteristicUUID, + properties: SensorLocationProperties, + value: Data (bytes: [0x0D]), + permissions: SensorLocationPermissions) + + let CSCMeasurementProperties: CBCharacteristicProperties = [.notify, .read] + let CSCMeasurementPermissions: CBAttributePermissions = [.readable] + self.CSCMeasurementCharacteristic = CBMutableCharacteristic(type: CSCMeasurementCharacteristicUUID, + properties: CSCMeasurementProperties, + value: nil, + permissions: CSCMeasurementPermissions) + + let SCControlPointProperties: CBCharacteristicProperties = [.indicate, .write] + let SCControlPointPermissions: CBAttributePermissions = [.writeable] + self.SCControlPointCharacteristic = CBMutableCharacteristic(type: SCControlPointCharacteristicUUID, + properties: SCControlPointProperties, + value: nil, + permissions: SCControlPointPermissions) + + CSCService.characteristics = [CSCFeatureCharacteristic, + SensorLocationCharacteristic, + CSCMeasurementCharacteristic, + SCControlPointCharacteristic] + self.peripheralManager.add(CSCService) + } self.PowerService = CBMutableService(type: PowerServiceUUID, primary: true) let PowerFeatureProperties: CBCharacteristicProperties = [.read] @@ -260,8 +263,13 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { print("Failed to add service with error: \(uwError.localizedDescription)") return } - - if(disable_hr) { + + + if(garmin_bluetooth_compatibility) { + let advertisementData = [CBAdvertisementDataLocalNameKey: "QZ", + CBAdvertisementDataServiceUUIDsKey: [PowerServiceUUID]] as [String : Any] + peripheralManager.startAdvertising(advertisementData) + } else if(disable_hr) { // useful in order to hide HR from Garmin devices let advertisementData = [CBAdvertisementDataLocalNameKey: "QZ", CBAdvertisementDataServiceUUIDsKey: [FitnessMachineServiceUuid, CSCServiceUUID, PowerServiceUUID]] as [String : Any] @@ -272,7 +280,6 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { peripheralManager.startAdvertising(advertisementData) } - print("Successfully added service") } @@ -371,13 +378,84 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { return cadenceData } + + private var revolutions: UInt16 = 0 + private var timestamp: UInt16 = 0 + private var lastRevolution: UInt64 = UInt64(Date().timeIntervalSince1970 * 1000) + func calculatePower() -> Data { - let flags:UInt8 = 0x20 - //self.delegate?.BLEPeripheralManagerCSCDidSendValue(flags, crankRevolutions: self.crankRevolutions, lastCrankEventTime: self.lastCrankEventTime) - var power: [UInt8] = [flags, 0x00, (UInt8)(self.CurrentWatt & 0xFF), (UInt8)((self.CurrentWatt >> 8) & 0xFF), (UInt8)(crankRevolutions & 0xFF), (UInt8)((crankRevolutions >> 8) & 0xFF), (UInt8)(lastCrankEventTime & 0xFF), (UInt8)((lastCrankEventTime >> 8) & 0xFF)] - let powerData = Data(bytes: &power, count: MemoryLayout.size(ofValue: power)) - return powerData - } + if(garmin_bluetooth_compatibility) { + /* + // convert RPM to timestamp + if (cadenceInstantaneous != 0 && (millis()) >= (lastRevolution + (60000 / cadenceInstantaneous))) + { + revolutions++; // One crank revolution should have passed, add one revolution + timestamp = (unsigned short)(((millis() * 1024) / 1000) % 65536); // create timestamp and format + lastRevolution = millis(); + } + */ + + let millis : UInt64 = UInt64(Date().timeIntervalSince1970 * 1000) + if CurrentCadence != 0 && (millis >= lastRevolution + (60000 / UInt64(CurrentCadence / 2))) { + revolutions = revolutions + 1 + var newT: UInt64 = ((60000 / (UInt64(CurrentCadence / 2)) * 1024) / 1000) + newT = newT + UInt64(timestamp) + newT = newT % 65536 + timestamp = UInt16(newT) + lastRevolution = millis + } + + let flags:UInt8 = 0x20 + //self.delegate?.BLEPeripheralManagerCSCDidSendValue(flags, crankRevolutions: self.crankRevolutions, lastCrankEventTime: self.lastCrankEventTime) + var power: [UInt8] = [flags, 0x00, (UInt8)(self.CurrentWatt & 0xFF), (UInt8)((self.CurrentWatt >> 8) & 0xFF), (UInt8)(revolutions & 0xFF), (UInt8)((revolutions >> 8) & 0xFF), (UInt8)(timestamp & 0xFF), (UInt8)((timestamp >> 8) & 0xFF)] + let powerData = Data(bytes: &power, count: MemoryLayout.size(ofValue: power)) + return powerData + } else { + let flags:UInt8 = 0x30 + + /* + // set measurement + measurement[2] = power & 0xFF; + measurement[3] = (power >> 8) & 0xFF; + measurement[4] = wheelrev & 0xFF; + measurement[5] = (wheelrev >> 8) & 0xFF; + measurement[6] = (wheelrev >> 16) & 0xFF; + measurement[7] = (wheelrev >> 24) & 0xFF; + measurement[8] = lastwheel & 0xFF; + measurement[9] = (lastwheel >> 8) & 0xFF; + measurement[10] = crankrev & 0xFF; + measurement[11] = (crankrev >> 8) & 0xFF; + measurement[12] = lastcrank & 0xFF; + measurement[13] = (lastcrank >> 8) & 0xFF; + + // speed & distance + // NOTE : based on Apple Watch default wheel dimension 700c x 2.5mm + // NOTE : 3 is theoretical crank:wheel gear ratio + // NOTE : 2.13 is circumference of 700c in meters + + wheelCount = crankCount * 3; + speed = cadence * 3 * 2.13 * 60 / 1000; + distance = wheelCount * 2.13 / 1000; + #if defined(USEPOWER) + lastWheelK = lastCrankK * 2; // 1/2048 s granularity + #else + lastWheelK = lastCrankK * 1; // 1/1024 s granularity + #endif + + */ + + //self.delegate?.BLEPeripheralManagerCSCDidSendValue(flags, crankRevolutions: self.crankRevolutions, lastCrankEventTime: self.lastCrankEventTime) + let wheelrev: UInt32 = ((UInt32)(crankRevolutions)) * 3; + let lastWheel: UInt16 = (UInt16)((((UInt32)(lastCrankEventTime)) * 2) & 0xFFFF); + var power: [UInt8] = [flags, 0x00, (UInt8)(self.CurrentWatt & 0xFF), (UInt8)((self.CurrentWatt >> 8) & 0xFF), + (UInt8)(wheelrev & 0xFF), (UInt8)((wheelrev >> 8) & 0xFF), (UInt8)((wheelrev >> 16) & 0xFF), (UInt8)((wheelrev >> 24) & 0xFF), + (UInt8)(lastWheel & 0xFF), (UInt8)((lastWheel >> 8) & 0xFF), + (UInt8)(crankRevolutions & 0xFF), (UInt8)((crankRevolutions >> 8) & 0xFF), + (UInt8)(lastCrankEventTime & 0xFF), (UInt8)((lastCrankEventTime >> 8) & 0xFF)] + let powerData = Data(bytes: &power, count: MemoryLayout.size(ofValue: power)) + return powerData + } + } func calculateHeartRate() -> Data { //self.delegate?.BLEPeripheralManagerDidSendValue(self.heartRate) @@ -397,35 +475,27 @@ class BLEPeripheralManagerZwift: NSObject, CBPeripheralManagerDelegate { } @objc func updateSubscribers() { - let heartRateData = self.calculateHeartRate() - let indoorBikeData = self.calculateIndoorBike() - let cadenceData = self.calculateCadence() - let powerData = self.calculatePower() - - if(self.serviceToggle == 3) + if(self.serviceToggle == 3 || garmin_bluetooth_compatibility) { + let powerData = self.calculatePower() let ok = self.peripheralManager.updateValue(powerData, for: self.PowerMeasurementCharacteristic, onSubscribedCentrals: nil) if(ok) { self.serviceToggle = 0 } - } - - if(self.serviceToggle == 2) - { + } else if(self.serviceToggle == 2) { + let cadenceData = self.calculateCadence() let ok = self.peripheralManager.updateValue(cadenceData, for: self.CSCMeasurementCharacteristic, onSubscribedCentrals: nil) if(ok) { self.serviceToggle = self.serviceToggle + 1 } - } - else if(self.serviceToggle == 1) - { + } else if(self.serviceToggle == 1) { + let heartRateData = self.calculateHeartRate() let ok = self.peripheralManager.updateValue(heartRateData, for: self.heartRateCharacteristic, onSubscribedCentrals: nil) if(ok) { self.serviceToggle = self.serviceToggle + 1 } - } - else - { + } else { + let indoorBikeData = self.calculateIndoorBike() let ok = self.peripheralManager.updateValue(indoorBikeData, for: self.indoorbikeCharacteristic, onSubscribedCentrals: nil) if(ok) { self.serviceToggle = self.serviceToggle + 1 diff --git a/src/ios/virtualtreadmill_zwift.swift b/src/ios/virtualtreadmill_zwift.swift index c0a05068e..9a341d299 100644 --- a/src/ios/virtualtreadmill_zwift.swift +++ b/src/ios/virtualtreadmill_zwift.swift @@ -36,13 +36,14 @@ let treadmilldataUuid = CBUUID(string: "0x2ACD"); return peripheralManager.PowerRequested; } - @objc public func updateFTMS(normalizeSpeed: UInt16, currentCadence: UInt16, currentResistance: UInt8, currentWatt: UInt16, currentInclination: UInt16) -> Bool + @objc public func updateFTMS(normalizeSpeed: UInt16, currentCadence: UInt16, currentResistance: UInt8, currentWatt: UInt16, currentInclination: UInt16, currentDistance: UInt64) -> Bool { peripheralManager.NormalizeSpeed = normalizeSpeed peripheralManager.CurrentCadence = currentCadence peripheralManager.CurrentResistance = currentResistance peripheralManager.CurrentWatt = currentWatt peripheralManager.CurrentInclination = currentInclination + peripheralManager.CurrentDistance = currentDistance return peripheralManager.connected; } @@ -70,6 +71,7 @@ class BLEPeripheralManagerTreadmillZwift: NSObject, CBPeripheralManagerDelegate public var CurrentResistance: UInt8! = 0 public var CurrentWatt: UInt16! = 0 public var CurrentInclination: UInt16! = 0 + public var CurrentDistance: UInt64! = 0 public var lastCurrentSlope: UInt64! = 0; public var serviceToggle: UInt8 = 0 @@ -314,14 +316,15 @@ class BLEPeripheralManagerTreadmillZwift: NSObject, CBPeripheralManagerDelegate } func calculateTreadmillData() -> Data { - let flags0:UInt8 = 0x08 + let flags0:UInt8 = 0x0C let flags1:UInt8 = 0x01 var treadmillData: [UInt8] = [flags0, flags1, (UInt8)(self.NormalizeSpeed & 0xFF), (UInt8)((self.NormalizeSpeed >> 8) & 0xFF), + (UInt8)(self.CurrentDistance & 0xFF), (UInt8)((self.CurrentDistance >> 8) & 0xFF), (UInt8)((self.CurrentDistance >> 16) & 0xFF), (UInt8)(self.CurrentInclination & 0xFF), (UInt8)((self.CurrentInclination >> 8) & 0xFF), (UInt8)(self.CurrentInclination & 0xFF), (UInt8)((self.CurrentInclination >> 8) & 0xFF), self.heartRate] - let treadmillDataData = Data(bytes: &treadmillData, count: 10) + let treadmillDataData = Data(bytes: &treadmillData, count: 13) return treadmillDataData } diff --git a/src/keepbike.cpp b/src/keepbike.cpp index 2138b660d..278a15fe5 100644 --- a/src/keepbike.cpp +++ b/src/keepbike.cpp @@ -186,6 +186,7 @@ double keepbike::bikeResistanceToPeloton(double resistance) { } void keepbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -220,7 +221,7 @@ void keepbike::characteristicChanged(const QLowEnergyCharacteristic &characteris { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } m_watt = GetWattFromPacket(newValue); @@ -231,17 +232,17 @@ void keepbike::characteristicChanged(const QLowEnergyCharacteristic &characteris settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (Cadence.value() > 0) { CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) { diff --git a/src/kingsmithr2treadmill.cpp b/src/kingsmithr2treadmill.cpp index 22d18a34c..c06d2367f 100644 --- a/src/kingsmithr2treadmill.cpp +++ b/src/kingsmithr2treadmill.cpp @@ -67,6 +67,8 @@ void kingsmithr2treadmill::writeCharacteristic(const QString &data, const QStrin encrypted.append(ENCRYPT_TABLE_v4[idx]); else if (settings.value(QZSettings::kingsmith_encrypt_v5, QZSettings::default_kingsmith_encrypt_v5).toBool()) encrypted.append(ENCRYPT_TABLE_v5[idx]); + else if (settings.value(QZSettings::kingsmith_encrypt_g1_walking_pad, QZSettings::default_kingsmith_encrypt_g1_walking_pad).toBool()) + encrypted.append(ENCRYPT_TABLE_v6[idx]); else encrypted.append(ENCRYPT_TABLE[idx]); } @@ -269,6 +271,8 @@ void kingsmithr2treadmill::characteristicChanged(const QLowEnergyCharacteristic idx = ENCRYPT_TABLE_v4.indexOf(ch); else if (settings.value(QZSettings::kingsmith_encrypt_v5, QZSettings::default_kingsmith_encrypt_v5).toBool()) idx = ENCRYPT_TABLE_v5.indexOf(ch); + else if (settings.value(QZSettings::kingsmith_encrypt_g1_walking_pad, QZSettings::default_kingsmith_encrypt_g1_walking_pad).toBool()) + idx = ENCRYPT_TABLE_v6.indexOf(ch); else idx = ENCRYPT_TABLE.indexOf(ch); decrypted.append(PLAINTEXT_TABLE[idx]); @@ -407,6 +411,9 @@ void kingsmithr2treadmill::stateChanged(QLowEnergyService::ServiceState state) { if (KS_NACH_X21C) { _gattWriteCharacteristicId = QBluetoothUuid(QStringLiteral("0002FED7-0000-1000-8000-00805f9b34fb")); _gattNotifyCharacteristicId = QBluetoothUuid(QStringLiteral("0002FED8-0000-1000-8000-00805f9b34fb")); + } else if (KS_NGCH_G1C) { + _gattWriteCharacteristicId = QBluetoothUuid(QStringLiteral("0001FED7-0000-1000-8000-00805f9b34fb")); + _gattNotifyCharacteristicId = QBluetoothUuid(QStringLiteral("0001FED8-0000-1000-8000-00805f9b34fb")); } QMetaEnum metaEnum = QMetaEnum::fromType(); @@ -460,6 +467,8 @@ void kingsmithr2treadmill::serviceScanDone(void) { if (KS_NACH_X21C) _gattCommunicationChannelServiceId = QBluetoothUuid(QStringLiteral("00021234-0000-1000-8000-00805f9b34fb")); + else if(KS_NGCH_G1C) + _gattCommunicationChannelServiceId = QBluetoothUuid(QStringLiteral("00011234-0000-1000-8000-00805f9b34fb")); gattCommunicationChannelService = m_control->createServiceObject(_gattCommunicationChannelServiceId); connect(gattCommunicationChannelService, &QLowEnergyService::stateChanged, this, @@ -488,7 +497,11 @@ void kingsmithr2treadmill::deviceDiscovered(const QBluetoothDeviceInfo &device) if (device.name().toUpper().startsWith(QStringLiteral("KS-NACH-X21C"))) { qDebug() << "KS-NACH-X21C workaround!"; KS_NACH_X21C = true; + } else if (device.name().toUpper().startsWith(QStringLiteral("KS-NGCH-G1C"))) { + qDebug() << "KS-NGCH-G1C workaround!"; + KS_NGCH_G1C = true; } + m_control = QLowEnergyController::createCentral(bluetoothDevice, this); connect(m_control, &QLowEnergyController::serviceDiscovered, this, &kingsmithr2treadmill::serviceDiscovered); connect(m_control, &QLowEnergyController::discoveryFinished, this, &kingsmithr2treadmill::serviceScanDone); diff --git a/src/kingsmithr2treadmill.h b/src/kingsmithr2treadmill.h index 0c63b8d63..90ec55f6b 100644 --- a/src/kingsmithr2treadmill.h +++ b/src/kingsmithr2treadmill.h @@ -56,6 +56,8 @@ class kingsmithr2treadmill : public treadmill { QStringLiteral("ZaCw4FGHIJqLhN9P+RVTU/WcY6ObDdefgEijklmnopQrsBuvMxXz1yA2t5078KS3=").toUtf8(); const QByteArray ENCRYPT_TABLE_v5 = QStringLiteral("iaCw4FGHIJqLhN+P9RVTU/WcY6ObDdefgEZjklmnopQrsBuvMxXz1yA2t5078KS3=").toUtf8(); + const QByteArray ENCRYPT_TABLE_v6 = + QStringLiteral("ZaCw4FGHIJqLhN+P8RVTU/WcY6ObDdefgEijklmnopQrsBuvMxXz1yA2t5079KS3=").toUtf8(); double GetInclinationFromPacket(const QByteArray &packet); double GetKcalFromPacket(const QByteArray &packet); @@ -88,6 +90,7 @@ class kingsmithr2treadmill : public treadmill { bool initRequest = false; bool KS_NACH_X21C = false; + bool KS_NGCH_G1C = false; #ifdef Q_OS_IOS lockscreen *h = 0; diff --git a/src/lifefitnesstreadmill.cpp b/src/lifefitnesstreadmill.cpp index b576da836..e720b5d3f 100644 --- a/src/lifefitnesstreadmill.cpp +++ b/src/lifefitnesstreadmill.cpp @@ -398,7 +398,7 @@ void lifefitnesstreadmill::characteristicChanged(const QLowEnergyCharacteristic if (Flags.heartRate) { if (index < newValue.length()) { - heart = ((double)((newValue.at(index)))); + heart = ((double)(((uint8_t)newValue.at(index)))); emit debug(QStringLiteral("Current Heart: ") + QString::number(heart)); } else { emit debug(QStringLiteral("Error on parsing heart!")); @@ -573,7 +573,7 @@ void lifefitnesstreadmill::characteristicChanged(const QLowEnergyCharacteristic #endif { if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) { - Heart = ((double)((newValue.at(index)))); + Heart = ((double)(((uint8_t)newValue.at(index)))); // index += 1; // NOTE: clang-analyzer-deadcode.DeadStores emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); } else { diff --git a/src/main.cpp b/src/main.cpp index ad68224b7..d317af74f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -282,7 +282,6 @@ void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QS } int main(int argc, char *argv[]) { - #ifdef Q_OS_WIN32 qputenv("QT_MULTIMEDIA_PREFERRED_PLUGINS", "windowsmediafoundation"); #endif diff --git a/src/main.qml b/src/main.qml index bd750d059..8d30b837d 100644 --- a/src/main.qml +++ b/src/main.qml @@ -22,6 +22,8 @@ ApplicationWindow { signal gpxpreview_open_clicked(url name) signal profile_open_clicked(url name) signal trainprogram_open_clicked(url name) + signal trainprogram_open_other_folder(url name) + signal gpx_open_other_folder(url name) signal trainprogram_preview(url name) signal trainprogram_zwo_loaded(string s) signal gpx_save_clicked() @@ -658,6 +660,7 @@ ApplicationWindow { onClicked: { stackView.push("GPXList.qml") stackView.currentItem.trainprogram_open_clicked.connect(gpx_open_clicked) + stackView.currentItem.trainprogram_open_other_folder.connect(gpx_open_other_folder) stackView.currentItem.trainprogram_preview.connect(gpxpreview_open_clicked) stackView.currentItem.trainprogram_open_clicked.connect(function(url) { stackView.pop(); @@ -673,6 +676,7 @@ ApplicationWindow { onClicked: { stackView.push("TrainingProgramsList.qml") stackView.currentItem.trainprogram_open_clicked.connect(trainprogram_open_clicked) + stackView.currentItem.trainprogram_open_other_folder.connect(trainprogram_open_other_folder) stackView.currentItem.trainprogram_preview.connect(trainprogram_preview) stackView.currentItem.trainprogram_open_clicked.connect(function(url) { stackView.pop(); @@ -747,7 +751,7 @@ ApplicationWindow { } ItemDelegate { - text: "version 2.16.24" + text: "version 2.16.32" width: parent.width } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index cc21774ec..4e24e4d26 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -356,14 +356,14 @@ void MainWindow::loadTrainProgram(const QString &fileName) { delete trainProgram; } - trainProgram = trainprogram::load(fileName, bluetoothManager); + trainProgram = trainprogram::load(fileName, bluetoothManager, fileName.right(3).toUpper()); } else if (fileName.endsWith(QStringLiteral("gpx"))) { if (trainProgram) { delete trainProgram; } gpx g; QList list; - auto g_list = g.open(fileName); + auto g_list = g.open(fileName, bluetoothManager->device() ? bluetoothManager->device()->deviceType() : bluetoothdevice::BIKE); list.reserve(g_list.count() + 1); for (const auto &p : qAsConst(g_list)) { trainrow r; diff --git a/src/mcfbike.cpp b/src/mcfbike.cpp index 3fe120d43..96b97afbd 100644 --- a/src/mcfbike.cpp +++ b/src/mcfbike.cpp @@ -177,6 +177,7 @@ double mcfbike::bikeResistanceToPeloton(double resistance) { } void mcfbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -210,11 +211,11 @@ void mcfbike::characteristicChanged(const QLowEnergyCharacteristic &characterist } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); m_watt = (((uint16_t)newValue.at(9) << 8) | (uint16_t)((uint8_t)newValue.at(10))); @@ -222,14 +223,14 @@ void mcfbike::characteristicChanged(const QLowEnergyCharacteristic &characterist KCal += ((((0.048 * ((double)watts()) + 1.19) * settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / - (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())))); + (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo(now)))); if (Cadence.value() > 0) { CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; qDebug() << QStringLiteral("Current Speed: ") + QString::number(Speed.value()); qDebug() << QStringLiteral("Current Calculate Distance: ") + QString::number(Distance.value()); diff --git a/src/mepanelbike.cpp b/src/mepanelbike.cpp index e0d51ec8a..891ca38af 100644 --- a/src/mepanelbike.cpp +++ b/src/mepanelbike.cpp @@ -130,6 +130,7 @@ void mepanelbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void mepanelbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -156,7 +157,7 @@ void mepanelbike::characteristicChanged(const QLowEnergyCharacteristic &characte } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } break; @@ -233,17 +234,17 @@ void mepanelbike::characteristicChanged(const QLowEnergyCharacteristic &characte settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (Cadence.value() > 0) { CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool() && disable_hr_frommachinery) { diff --git a/src/metric.cpp b/src/metric.cpp index 31c174567..426920949 100644 --- a/src/metric.cpp +++ b/src/metric.cpp @@ -323,7 +323,10 @@ double metric::powerPeak(QList *session, int seconds) { std::sort(bests.begin(), bests.end(), CompareBests()); - return bests.first().avg; + if(bests.length() > 0) + return bests.first().avg; + else + return 0; } // VO2 (L/min) = 0.0108 x power (W) + 0.007 x body mass (kg) diff --git a/src/metric.h b/src/metric.h index c13be8668..19e13125f 100644 --- a/src/metric.h +++ b/src/metric.h @@ -42,8 +42,6 @@ class metric { void operator+=(double); void setPaused(bool p); void setLap(bool accumulator); - void setColor(QString color) { m_color = color; } - QString color() { return m_color; } static double calculateMaxSpeedFromPower(double power, double inclination); static double calculatePowerFromSpeed(double speed, double inclination); @@ -54,7 +52,7 @@ class metric { static double calculateKCalfromHR(double HR_AVG, double elapsed); static double powerPeak(QList *session, int seconds); - + private: double m_value = 0; double m_totValue = 0; @@ -77,7 +75,6 @@ class metric { _metric_type m_type = METRIC_OTHER; bool paused = false; - QString m_color; }; #endif // METRIC_H diff --git a/src/nautilusbike.cpp b/src/nautilusbike.cpp index e6c146ef4..360e9ac16 100644 --- a/src/nautilusbike.cpp +++ b/src/nautilusbike.cpp @@ -132,6 +132,7 @@ void nautilusbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void nautilusbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); @@ -172,7 +173,7 @@ void nautilusbike::characteristicChanged(const QLowEnergyCharacteristic &charact if (watts()) KCal += ((((0.048 * ((double)watts()) + 1.19) * weight * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 // double kcal = GetKcalFromPacket(newValue); // double distance = GetDistanceFromPacket(newValue) * @@ -189,11 +190,11 @@ void nautilusbike::characteristicChanged(const QLowEnergyCharacteristic &charact Speed = speed; Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; emit debug(QStringLiteral("Current speed: ") + QString::number(speed)); emit debug(QStringLiteral("Current cadence: ") + QString::number(Cadence.value())); diff --git a/src/nordictrackifitadbbike.cpp b/src/nordictrackifitadbbike.cpp index eeb9868e4..839037346 100644 --- a/src/nordictrackifitadbbike.cpp +++ b/src/nordictrackifitadbbike.cpp @@ -124,6 +124,8 @@ nordictrackifitadbbike::nordictrackifitadbbike(bool noWriteResistance, bool noHe processPendingDatagrams(); connect(socket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams())); + initRequest = true; + // ******************************************* virtual treadmill init ************************************* if (!firstStateChanged && !this->hasVirtualDevice()) { bool virtual_device_enabled = @@ -200,6 +202,7 @@ void nordictrackifitadbbike::processPendingDatagrams() { QHostAddress sender; QSettings settings; uint16_t port; + bool freemotion_coachbike_b22_7 = settings.value(QZSettings::freemotion_coachbike_b22_7, QZSettings::default_freemotion_coachbike_b22_7).toBool(); while (socket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(socket->pendingDatagramSize()); @@ -247,7 +250,10 @@ void nordictrackifitadbbike::processPendingDatagrams() { QStringList aValues = line.split(" "); if (aValues.length()) { resistance = getDouble(aValues.last()); - m_pelotonResistance = (100 / 32) * resistance; + if(freemotion_coachbike_b22_7) + m_pelotonResistance = (100 / 24) * resistance; + else + m_pelotonResistance = (100 / 32) * resistance; qDebug() << QStringLiteral("Current Peloton Resistance: ") << m_pelotonResistance.value() << resistance; if(!gearsAvailable) @@ -322,15 +328,15 @@ void nordictrackifitadbbike::processPendingDatagrams() { if (requestInclination != -100) { double inc = qRound(requestInclination / 0.5) * 0.5; if (inc != currentInclination().value()) { - bool proform_studio = settings.value(QZSettings::proform_studio, QZSettings::default_proform_studio).toBool(); + bool proform_studio = settings.value(QZSettings::proform_studio, QZSettings::default_proform_studio).toBool(); int x1 = 75; int y2 = (int)(616.18 - (17.223 * (inc + gears()))); int y1Resistance = (int)(616.18 - (17.223 * currentInclination().value())); - if(proform_studio) { - int x1 = 1827; - int y2 = (int)(806 - (21.375 * (inc + gears()))); - int y1Resistance = (int)(806 - (21.375 * currentInclination().value())); + if(proform_studio || freemotion_coachbike_b22_7) { + x1 = 1827; + y2 = (int)(806 - (21.375 * (inc + gears()))); + y1Resistance = (int)(806 - (21.375 * currentInclination().value())); } lastCommand = "input swipe " + QString::number(x1) + " " + QString::number(y1Resistance) + " " + @@ -349,6 +355,32 @@ void nordictrackifitadbbike::processPendingDatagrams() { h->adb_sendcommand(lastCommand.toStdString().c_str()); #endif #endif + // this bike has both inclination and resistance, let's try to handle both + // the Original Poster doesn't want anymore, but maybe it will be useful in the future + /* + if(freemotion_coachbike_b22_7) { + int x1 = 75; + int y2 = (int)(616.18 - (17.223 * (inc + gears()))); + int y1Resistance = (int)(616.18 - (17.223 * currentInclination().value())); + + lastCommand = "input swipe " + QString::number(x1) + " " + QString::number(y1Resistance) + " " + + QString::number(x1) + " " + QString::number(y2) + " 200"; + qDebug() << " >> " + lastCommand; + #ifdef Q_OS_ANDROID + QAndroidJniObject command = QAndroidJniObject::fromString(lastCommand).object(); + QAndroidJniObject::callStaticMethod("org/cagnulen/qdomyoszwift/QZAdbRemote", + "sendCommand", "(Ljava/lang/String;)V", + command.object()); + #elif defined(Q_OS_WIN) + if (logcatAdbThread) + logcatAdbThread->runCommand("shell " + lastCommand); + #elif defined Q_OS_IOS + #ifndef IO_UNDER_QT + h->adb_sendcommand(lastCommand.toStdString().c_str()); + #endif + #endif + } + */ } } @@ -490,6 +522,11 @@ void nordictrackifitadbbike::update() { QSettings settings; update_metrics(false, 0); + if (initRequest) { + initRequest = false; + emit connectedAndDiscovered(); + } + // updating the treadmill console every second if (sec1Update++ == (500 / refresh->interval())) { sec1Update = 0; diff --git a/src/nordictrackifitadbtreadmill.cpp b/src/nordictrackifitadbtreadmill.cpp index 052efe348..b7118176f 100644 --- a/src/nordictrackifitadbtreadmill.cpp +++ b/src/nordictrackifitadbtreadmill.cpp @@ -22,9 +22,18 @@ void nordictrackifitadbtreadmillLogcatAdbThread::run() { QString ip = settings.value(QZSettings::nordictrack_2950_ip, QZSettings::default_nordictrack_2950_ip).toString(); runAdbCommand("connect " + ip); - while (1) { + while (!stop) + { runAdbTailCommand("logcat"); +#ifndef Q_OS_WINDOWS + if(adbCommandPending.length() != 0) { + runAdbCommand(adbCommandPending); + adbCommandPending = ""; + } + msleep(100); +#endif } + } QString nordictrackifitadbtreadmillLogcatAdbThread::runAdbCommand(QString command) { @@ -45,10 +54,22 @@ QString nordictrackifitadbtreadmillLogcatAdbThread::runAdbCommand(QString comman return out; } +bool nordictrackifitadbtreadmillLogcatAdbThread::runCommand(QString command) { + if(adbCommandPending.length() == 0) { + adbCommandPending = command; + return true; + } + return false; +} + void nordictrackifitadbtreadmillLogcatAdbThread::runAdbTailCommand(QString command) { #ifdef Q_OS_WINDOWS auto process = new QProcess; QObject::connect(process, &QProcess::readyReadStandardOutput, [process, this]() { + if(stop) { + process->close(); + return; + } QString output = process->readAllStandardOutput(); qDebug() << "adbLogCat STDOUT << " << output; QStringList lines = output.split('\n', Qt::SplitBehaviorFlags::SkipEmptyParts); @@ -69,6 +90,12 @@ void nordictrackifitadbtreadmillLogcatAdbThread::runAdbTailCommand(QString comma emit onSpeedInclination(speed, inclination); if (wattFound) emit onWatt(watt); +#ifdef Q_OS_WINDOWS + if(adbCommandPending.length() != 0) { + runAdbCommand(adbCommandPending); + adbCommandPending = ""; + } +#endif }); QObject::connect(process, &QProcess::readyReadStandardError, [process, this]() { auto output = process->readAllStandardError(); @@ -100,12 +127,10 @@ nordictrackifitadbtreadmill::nordictrackifitadbtreadmill(bool noWriteResistance, this->noHeartService = noHeartService; initDone = false; connect(refresh, &QTimer::timeout, this, &nordictrackifitadbtreadmill::update); + connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &nordictrackifitadbtreadmill::stopLogcatAdbThread); QString ip = settings.value(QZSettings::nordictrack_2950_ip, QZSettings::default_nordictrack_2950_ip).toString(); refresh->start(200ms); -#ifdef Q_OS_WIN32 - if (!nordictrack_ifit_adb_remote) -#endif { socket = new QUdpSocket(this); bool result = socket->bind(QHostAddress::AnyIPv4, 8002); @@ -114,7 +139,7 @@ nordictrackifitadbtreadmill::nordictrackifitadbtreadmill(bool noWriteResistance, connect(socket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams())); } #ifdef Q_OS_WIN32 - else { + { logcatAdbThread = new nordictrackifitadbtreadmillLogcatAdbThread("logcatAdbThread"); connect(logcatAdbThread, &nordictrackifitadbtreadmillLogcatAdbThread::onSpeedInclination, this, &nordictrackifitadbtreadmill::onSpeedInclination); @@ -223,6 +248,21 @@ void nordictrackifitadbtreadmill::processPendingDatagrams() { } } + double inc = qRound(requestInclination / 0.5) * 0.5; + if(inc == currentInclination().value()) { + qDebug() << "ignoring inclination" << requestInclination; + requestInclination = -100; + } + + int currentRequestInclination = requestInclination; + + // since the motor of the treadmill is slow, let's filter the inclination changes to more than 1 second + if (requestInclination != -100 && lastInclinationChanged.secsTo(QDateTime::currentDateTime()) > 1) { + lastInclinationChanged = QDateTime::currentDateTime(); + } else { + currentRequestInclination = -100; + } + bool nordictrack_ifit_adb_remote = settings.value(QZSettings::nordictrack_ifit_adb_remote, QZSettings::default_nordictrack_ifit_adb_remote) .toBool(); @@ -231,9 +271,9 @@ void nordictrackifitadbtreadmill::processPendingDatagrams() { settings.value(QZSettings::nordictrack_x22i, QZSettings::default_nordictrack_x22i).toBool(); if (requestSpeed != -1) { int x1 = 1845; - int y1Speed = 807 - (int)((Speed.value() - 1) * 29.78); + int y1Speed = 807 - (int)((Speed.value() - 1) * 31); // set speed slider to target position - int y2 = y1Speed - (int)((requestSpeed - Speed.value()) * 29.78); + int y2 = y1Speed - (int)((requestSpeed - Speed.value()) * 31); if(nordictrack_x22i) { x1 = 1845; y1Speed = (int) (785 - (23.636 * (Speed.value() - 1))); @@ -247,51 +287,56 @@ void nordictrackifitadbtreadmill::processPendingDatagrams() { QAndroidJniObject command = QAndroidJniObject::fromString(lastCommand).object(); QAndroidJniObject::callStaticMethod("org/cagnulen/qdomyoszwift/QZAdbRemote", "sendCommand", "(Ljava/lang/String;)V", command.object()); +#elif defined(Q_OS_WIN) + if (logcatAdbThread) + logcatAdbThread->runCommand("shell " + lastCommand); #elif defined Q_OS_IOS #ifndef IO_UNDER_QT h->adb_sendcommand(lastCommand.toStdString().c_str()); #endif #endif requestSpeed = -1; - } else if (requestInclination != -100) { - double inc = qRound(requestInclination / 0.5) * 0.5; - if(inc != currentInclination().value()) { - requestInclination = inc; - int x1 = 75; - int y1Inclination = 807 - (int)((currentInclination().value() + 3) * 29.9); - // set speed slider to target position - int y2 = y1Inclination - (int)((requestInclination - currentInclination().value()) * 29.9); - - if(nordictrack_x22i) { - x1 = 75; - y1Inclination = (int) (785 - (11.304 * (currentInclination().value() + 6))); - y2 = y1Inclination - (int)((requestInclination - currentInclination().value()) * 11.304); - } - - lastCommand = "input swipe " + QString::number(x1) + " " + QString::number(y1Inclination) + " " + - QString::number(x1) + " " + QString::number(y2) + " 200"; - qDebug() << " >> " + lastCommand; + } else if (currentRequestInclination != -100) { + requestInclination = inc; + int x1 = 75; + int y1Inclination = 807 - (int)((currentInclination().value() + 3) * 31.1); + // set speed slider to target position + int y2 = y1Inclination - (int)((requestInclination - currentInclination().value()) * 31.1); + + if(nordictrack_x22i) { + x1 = 75; + y1Inclination = (int) (785 - (11.304 * (currentInclination().value() + 6))); + y2 = y1Inclination - (int)((requestInclination - currentInclination().value()) * 11.304); + } + + lastCommand = "input swipe " + QString::number(x1) + " " + QString::number(y1Inclination) + " " + + QString::number(x1) + " " + QString::number(y2) + " 200"; + qDebug() << " >> " + lastCommand; #ifdef Q_OS_ANDROID - QAndroidJniObject command = QAndroidJniObject::fromString(lastCommand).object(); - QAndroidJniObject::callStaticMethod("org/cagnulen/qdomyoszwift/QZAdbRemote", "sendCommand", - "(Ljava/lang/String;)V", command.object()); + QAndroidJniObject command = QAndroidJniObject::fromString(lastCommand).object(); + QAndroidJniObject::callStaticMethod("org/cagnulen/qdomyoszwift/QZAdbRemote", "sendCommand", + "(Ljava/lang/String;)V", command.object()); +#elif defined(Q_OS_WIN) + if (logcatAdbThread) + logcatAdbThread->runCommand("shell " + lastCommand); #elif defined Q_OS_IOS #ifndef IO_UNDER_QT - h->adb_sendcommand(lastCommand.toStdString().c_str()); + h->adb_sendcommand(lastCommand.toStdString().c_str()); #endif #endif - } requestInclination = -100; } } - QByteArray message = (QString::number(requestSpeed) + ";" + QString::number(requestInclination)).toLocal8Bit(); - // we have to separate the 2 commands - if (requestSpeed == -1) - requestInclination = -100; - requestSpeed = -1; - int ret = socket->writeDatagram(message, message.size(), sender, 8003); - qDebug() << QString::number(ret) + " >> " + message; + if(!nordictrack_ifit_adb_remote) { + QByteArray message = (QString::number(requestSpeed) + ";" + QString::number(currentRequestInclination)).toLocal8Bit(); + // we have to separate the 2 commands + if (requestSpeed == -1) + requestInclination = -100; + requestSpeed = -1; + int ret = socket->writeDatagram(message, message.size(), sender, 8003); + qDebug() << QString::number(ret) + " >> " + message; + } if (watts(weight)) KCal += @@ -439,3 +484,24 @@ void nordictrackifitadbtreadmill::changeInclinationRequested(double grade, doubl } bool nordictrackifitadbtreadmill::connected() { return true; } + +void nordictrackifitadbtreadmill::stopLogcatAdbThread() { + qDebug() << "stopLogcatAdbThread()"; + + initiateThreadStop(); + logcatAdbThread->quit(); + logcatAdbThread->terminate(); + +#ifdef Q_OS_WIN32 + QProcess process; + QString command = "/c wmic process where name='adb.exe' delete"; + process.start("cmd.exe", QStringList(command.split(' '))); + process.waitForFinished(-1); // will wait forever until finished +#endif + + logcatAdbThread->wait(); +} + +void nordictrackifitadbtreadmill::initiateThreadStop() { + logcatAdbThread->stop = true; +} diff --git a/src/nordictrackifitadbtreadmill.h b/src/nordictrackifitadbtreadmill.h index 990e7c035..ec50e3963 100644 --- a/src/nordictrackifitadbtreadmill.h +++ b/src/nordictrackifitadbtreadmill.h @@ -30,8 +30,10 @@ class nordictrackifitadbtreadmillLogcatAdbThread : public QThread { public: explicit nordictrackifitadbtreadmillLogcatAdbThread(QString s); + bool runCommand(QString command); void run() override; + bool stop = false; signals: void onSpeedInclination(double speed, double inclination); @@ -39,6 +41,7 @@ class nordictrackifitadbtreadmillLogcatAdbThread : public QThread { void onWatt(double watt); private: + QString adbCommandPending = ""; double speed = 0; double inclination = 0; double watt = 0; @@ -63,11 +66,13 @@ class nordictrackifitadbtreadmill : public treadmill { void forceIncline(double incline); void forceSpeed(double speed); double getDouble(QString v); + void initiateThreadStop(); QTimer *refresh; uint8_t sec1Update = 0; QDateTime lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + QDateTime lastInclinationChanged = QDateTime::currentDateTime(); uint8_t firstStateChanged = 0; uint16_t m_watts = 0; bool wattReadFromTM = false; @@ -102,6 +107,9 @@ class nordictrackifitadbtreadmill : public treadmill { void changeInclinationRequested(double grade, double percentage); void update(); + + public slots: + void stopLogcatAdbThread(); }; -#endif // NORDICTRACKIFITADBTREADMILL_H +#endif // NORDICTRACKIFITADBTREADMILL_H \ No newline at end of file diff --git a/src/npecablebike.cpp b/src/npecablebike.cpp index 44ce83f1b..f76250f00 100644 --- a/src/npecablebike.cpp +++ b/src/npecablebike.cpp @@ -111,6 +111,7 @@ void npecablebike::serviceDiscovered(const QBluetoothUuid &gatt) { } void npecablebike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -167,8 +168,8 @@ void npecablebike::characteristicChanged(const QLowEnergyCharacteristic &charact if (cadence >= 0) { Cadence = cadence; } - lastGoodCadence = QDateTime::currentDateTime(); - } else if (lastGoodCadence.msecsTo(QDateTime::currentDateTime()) > 2000) { + lastGoodCadence = now; + } else if (lastGoodCadence.msecsTo(now) > 2000) { Cadence = 0; } } @@ -181,12 +182,12 @@ void npecablebike::characteristicChanged(const QLowEnergyCharacteristic &charact if (!settings.value(QZSettings::speed_power_based, QZSettings::default_speed_power_based).toBool()) { Speed = Cadence.value() * settings.value(QZSettings::cadence_sensor_speed_ratio, QZSettings::default_cadence_sensor_speed_ratio).toDouble(); } else { - Speed = metric::calculateSpeedFromPower(watts(), Inclination.value(), Speed.value(),fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + Speed = metric::calculateSpeedFromPower(watts(), Inclination.value(), Speed.value(),fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); // Resistance = ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | @@ -200,7 +201,7 @@ void npecablebike::characteristicChanged(const QLowEnergyCharacteristic &charact 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); } else if (characteristic.uuid() == QBluetoothUuid::HeartRateMeasurement) { @@ -250,7 +251,7 @@ void npecablebike::characteristicChanged(const QLowEnergyCharacteristic &charact (uint16_t)((uint8_t)newValue.at(index)))) / 100.0; } else { - Speed = metric::calculateSpeedFromPower(watts(), Inclination.value(), Speed.value(),fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + Speed = metric::calculateSpeedFromPower(watts(), Inclination.value(), Speed.value(),fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } index += 2; emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); @@ -294,7 +295,7 @@ void npecablebike::characteristicChanged(const QLowEnergyCharacteristic &charact index += 3; } else { Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); } emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); @@ -362,7 +363,7 @@ void npecablebike::characteristicChanged(const QLowEnergyCharacteristic &charact 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -375,7 +376,7 @@ void npecablebike::characteristicChanged(const QLowEnergyCharacteristic &charact #endif { if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) { - Heart = ((double)((newValue.at(index)))); + Heart = ((double)(((uint8_t)newValue.at(index)))); // index += 1; // NOTE: clang-analyzer-deadcode.DeadStores emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); } else { @@ -411,7 +412,7 @@ void npecablebike::characteristicChanged(const QLowEnergyCharacteristic &charact LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_IOS #ifndef IO_UNDER_QT diff --git a/src/octaneelliptical.cpp b/src/octaneelliptical.cpp index 2257de163..1b0f2a858 100644 --- a/src/octaneelliptical.cpp +++ b/src/octaneelliptical.cpp @@ -170,10 +170,18 @@ octaneelliptical::octaneelliptical(uint32_t pollDeviceTime, bool noConsole, bool actualPace2Sign.clear(); // SPEED + actualPaceSign.append(0x01); actualPaceSign.append(0x07); - actualPaceSign.append(0x03); + actualPace2Sign.append((char)0x00); actualPace2Sign.append(0x07); - actualPace2Sign.append(0x03); + + actualHR.append((char)0x02); + actualHR.append((char)0x11); + + actualResistance.append((char)0x01); + actualResistance.append((char)0x09); + + actualOdometer.append((char)0x0b); m_watt.setType(metric::METRIC_WATT); Speed.setType(metric::METRIC_SPEED); @@ -340,41 +348,66 @@ void octaneelliptical::characteristicChanged(const QLowEnergyCharacteristic &cha if ((newValue.length() != 20)) return; - if ((uint8_t)newValue[0] == 0xa5 && newValue[1] == 0x09) { - Resistance = (uint8_t)newValue[4]; - emit debug(QStringLiteral("Current resistance: ") + QString::number(Resistance.value())); - return; - } - - if (!newValue.contains(actualPaceSign) && !newValue.contains(actualPace2Sign)) - return; - - int16_t i = newValue.indexOf(actualPaceSign) + 2; - if (i <= 1) - i = newValue.indexOf(actualPace2Sign) + 2; + if (newValue.contains(actualResistance)) { + int16_t i = newValue.indexOf(actualResistance) + 2; - if (i + 1 >= newValue.length()) - return; + if (i + 1 < newValue.length()) { + Resistance = ((uint8_t)value.at(i)); + emit debug(QStringLiteral("Current resistance: ") + QString::number(Resistance.value())); + } + } - double speed = GetSpeedFromPacket(value, i); - if (isinf(speed)) - return; + if (newValue.contains(actualHR)) { + bool disable_hr_frommachinery = settings.value(QZSettings::heart_ignore_builtin, QZSettings::default_heart_ignore_builtin).toBool(); #ifdef Q_OS_ANDROID - if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) - Heart = (uint8_t)KeepAwakeHelper::heart(); - else + if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) + Heart = (uint8_t)KeepAwakeHelper::heart(); + else #endif - { - /*if(heartRateBeltName.startsWith("Disabled")) - Heart = value.at(18);*/ + { + if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) { + int16_t i = newValue.indexOf(actualHR) + 2; + + if (i + 1 < newValue.length()) { + uint8_t heart = ((uint8_t)value.at(i)); + if (heart == 0 || disable_hr_frommachinery) { + update_hr_from_external(); + } else { + Heart = heart; + } + } + } + } + emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); } - emit debug(QStringLiteral("Current speed: ") + QString::number(speed)); - if (Speed.value() != speed) { - emit speedChanged(speed); - } - Speed = speed; + int16_t i = newValue.indexOf(actualPaceSign) + 2; + /*if (i <= 1) + i = newValue.indexOf(actualPace2Sign) + 1;*/ + + if (i + 1 >= newValue.length() || i <= 1) { + // fallback for a previous firmware version + if(newValue.length() >= 20 && (uint8_t)newValue.at(0) == 0xa5) { + if(newValue.at(6) == 0x07) { + i = 7; + } else if(newValue.at(15) == 0x07) { + i = 16; + } else { + return; + } + } else { + return; + } + } + + Cadence = ((uint8_t)value.at(i)); + emit debug(QStringLiteral("Current Cadence: ") + QString::number(Cadence.value())); + + // Q37xi has a fixed stride length of 20.5 inches (52cm). + Speed = (((Cadence.value() / 2.0) * 52.07 * 60) / 10000) * 0.84135; + emit speedChanged(speed.value()); + emit debug(QStringLiteral("Current speed: ") + QString::number(Speed.value())); if (!firstCharacteristicChanged) { if (watts()) @@ -385,13 +418,12 @@ void octaneelliptical::characteristicChanged(const QLowEnergyCharacteristic &cha (60000.0 / ((double)lastTimeCharacteristicChanged.msecsTo( QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 - - Distance += ((Speed.value() / 3600.0) / - (1000.0 / (lastTimeCharacteristicChanged.msecsTo(QDateTime::currentDateTime())))); + Distance += ((Speed.value() / 3600000.0) * + ((double)lastTimeCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); lastTimeCharacteristicChanged = QDateTime::currentDateTime(); } - emit debug(QStringLiteral("Current Distance Calculated: ") + QString::number(Distance.value())); + emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); if (m_control->error() != QLowEnergyController::NoError) { @@ -402,8 +434,8 @@ void octaneelliptical::characteristicChanged(const QLowEnergyCharacteristic &cha } double octaneelliptical::GetSpeedFromPacket(const QByteArray &packet, int index) { - uint16_t convertedData = (packet.at(index + 4) << 8) | ((uint8_t)packet.at(index + 5)); - return ((double)convertedData) / 100.0; + uint16_t convertedData = ((uint8_t)packet.at(index)); + return ((double)convertedData) / 10.0; } void octaneelliptical::btinit(bool startTape) { diff --git a/src/octaneelliptical.h b/src/octaneelliptical.h index 6f590dede..ef565c047 100644 --- a/src/octaneelliptical.h +++ b/src/octaneelliptical.h @@ -62,6 +62,12 @@ class octaneelliptical : public elliptical { QByteArray actualPaceSign; QByteArray actualPace2Sign; + QByteArray actualHR; + QByteArray actualResistance; + QByteArray actualOdometer; + int distance = 0; + QDateTime lastTimeDistance = QDateTime::currentDateTime(); + metric speed; QTimer *refresh; diff --git a/src/pafersbike.cpp b/src/pafersbike.cpp index 7e698fbe4..d7c247469 100644 --- a/src/pafersbike.cpp +++ b/src/pafersbike.cpp @@ -192,6 +192,7 @@ double pafersbike::GetWattFromPacket(const QByteArray &packet) { } void pafersbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -216,7 +217,7 @@ void pafersbike::characteristicChanged(const QLowEnergyCharacteristic &character } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } Resistance = ((uint8_t)newValue.at(5)); @@ -230,17 +231,17 @@ void pafersbike::characteristicChanged(const QLowEnergyCharacteristic &character settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (Cadence.value() > 0) { CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) { diff --git a/src/proformbike.cpp b/src/proformbike.cpp index 78c44066b..8dc2d2500 100644 --- a/src/proformbike.cpp +++ b/src/proformbike.cpp @@ -162,6 +162,10 @@ void proformbike::forceResistance(resistance_t requestResistance) { .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_cycle_trainer_300_ci = + settings.value(QZSettings::proform_cycle_trainer_300_ci, QZSettings::default_proform_cycle_trainer_300_ci) + .toBool(); + bool proform_bike_225_csx = settings.value(QZSettings::proform_bike_225_csx, QZSettings::default_proform_bike_225_csx).toBool(); if (proform_studio || proform_tdf_10) { const uint8_t res1[] = {0xfe, 0x02, 0x16, 0x03}; @@ -265,7 +269,7 @@ void proformbike::forceResistance(resistance_t requestResistance) { writeCharacteristic((uint8_t *)res16, sizeof(res16), QStringLiteral("resistance16"), false, true); break; } - } else if (nordictrack_gx_2_7) { + } else if (nordictrack_gx_2_7 || proform_bike_225_csx) { const uint8_t res1[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01, 0x04, 0xc2, 0x01, 0x00, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00}; const uint8_t res2[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01, @@ -406,6 +410,11 @@ void proformbike::forceResistance(resistance_t requestResistance) { const uint8_t res16[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x07, 0x09, 0x02, 0x01, 0x04, 0xd1, 0x26, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00}; + if(proform_cycle_trainer_300_ci) { + uint8_t noOpData7[] = {0xfe, 0x02, 0x0d, 0x02}; + writeCharacteristic((uint8_t *)noOpData7, sizeof(noOpData7), QStringLiteral("resrequest"), false, false); + } + switch (requestResistance) { case 1: writeCharacteristic((uint8_t *)res1, sizeof(res1), QStringLiteral("resistance1"), false, true); @@ -509,6 +518,9 @@ void proformbike::update() { bool proform_tdf_10 = settings.value(QZSettings::proform_tdf_10, QZSettings::default_proform_tdf_10).toBool(); bool nordictrack_gx_2_7 = settings.value(QZSettings::nordictrack_gx_2_7, QZSettings::default_nordictrack_gx_2_7).toBool(); + bool proform_cycle_trainer_300_ci = + settings.value(QZSettings::proform_cycle_trainer_300_ci, QZSettings::default_proform_cycle_trainer_300_ci) + .toBool(); bool proform_cycle_trainer_400 = settings.value(QZSettings::proform_cycle_trainer_400, QZSettings::default_proform_cycle_trainer_400) .toBool(); @@ -521,6 +533,7 @@ void proformbike::update() { bool proform_bike_PFEVEX71316_1 = settings.value(QZSettings::proform_bike_PFEVEX71316_1, QZSettings::default_proform_bike_PFEVEX71316_1) .toBool(); + bool proform_bike_225_csx = settings.value(QZSettings::proform_bike_225_csx, QZSettings::default_proform_bike_225_csx).toBool(); uint8_t noOpData1[] = {0xfe, 0x02, 0x19, 0x03}; uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x07, 0x15, 0x02, 0x00, @@ -534,6 +547,13 @@ void proformbike::update() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t noOpData7[] = {0xfe, 0x02, 0x0d, 0x02}; + // proform_bike_225_csx + uint8_t noOpData2_proform_bike_225_csx[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x00, 0x0d, 0x3c, 0x96, 0x31, 0x00, 0x00, 0x40, 0x40, 0x00, 0x80}; + uint8_t noOpData3_proform_bike_225_csx[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x85, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData5_proform_bike_225_csx[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x07, 0x15, 0x02, 0x00, 0x0f, 0x80, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData6_proform_bike_225_csx[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + // proform_bike_sb uint8_t noOpData2_proform_bike_sb[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x00, 0x0d, 0x3c, 0x9e, 0x31, 0x00, 0x00, 0x40, 0x40, 0x00, 0x80}; @@ -601,7 +621,7 @@ void proformbike::update() { switch (counterPoll) { case 0: - if (nordictrack_gx_2_7 || proform_hybrid_trainer_PFEL03815 || proform_bike_sb) { + if (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci || proform_hybrid_trainer_PFEL03815 || proform_bike_sb || proform_bike_225_csx) { writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp")); } else { writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("noOp")); @@ -610,15 +630,18 @@ void proformbike::update() { case 1: if (proform_studio || proform_tdf_10) writeCharacteristic(noOpData2_proform_studio, sizeof(noOpData2_proform_studio), QStringLiteral("noOp")); - else if (nordictrack_gx_2_7) { + else if (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci) { writeCharacteristic(noOpData2_nordictrack_gx_2_7, sizeof(noOpData2_nordictrack_gx_2_7), QStringLiteral("noOp")); } else if (proform_hybrid_trainer_PFEL03815) { writeCharacteristic(noOpData2_proform_hybrid_trainer_PFEL03815, sizeof(noOpData2_proform_hybrid_trainer_PFEL03815), QStringLiteral("noOp")); - } else if (proform_tour_de_france_clc) + } else if (proform_tour_de_france_clc) { writeCharacteristic(noOpData2_proform_tour_de_france_clc, sizeof(noOpData2_proform_tour_de_france_clc), QStringLiteral("noOp")); + } else if (proform_bike_225_csx) + writeCharacteristic(noOpData2_proform_bike_225_csx, sizeof(noOpData2_proform_bike_225_csx), + QStringLiteral("noOp")); else if (proform_cycle_trainer_400) writeCharacteristic(noOpData2_proform_cycle_trainer_400, sizeof(noOpData2_proform_cycle_trainer_400), QStringLiteral("noOp")); @@ -637,15 +660,18 @@ void proformbike::update() { else if (proform_tour_de_france_clc) writeCharacteristic(noOpData3_proform_tour_de_france_clc, sizeof(noOpData3_proform_tour_de_france_clc), QStringLiteral("noOp")); - else if (nordictrack_gx_2_7) { + else if (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci) { writeCharacteristic(noOpData3_nordictrack_gx_2_7, sizeof(noOpData3_nordictrack_gx_2_7), QStringLiteral("noOp")); } else if (proform_hybrid_trainer_PFEL03815) { writeCharacteristic(noOpData3_proform_hybrid_trainer_PFEL03815, sizeof(noOpData3_proform_hybrid_trainer_PFEL03815), QStringLiteral("noOp")); - } else if (proform_cycle_trainer_400) + } else if (proform_cycle_trainer_400) { writeCharacteristic(noOpData3_proform_cycle_trainer_400, sizeof(noOpData3_proform_cycle_trainer_400), QStringLiteral("noOp")); + } else if (proform_bike_225_csx) + writeCharacteristic(noOpData3_proform_bike_225_csx, sizeof(noOpData3_proform_bike_225_csx), + QStringLiteral("noOp")); else if (proform_bike_sb) writeCharacteristic(noOpData3_proform_bike_sb, sizeof(noOpData3_proform_bike_sb), QStringLiteral("noOp")); @@ -658,7 +684,7 @@ void proformbike::update() { case 3: if (proform_studio || proform_tdf_10) writeCharacteristic(noOpData4_proform_studio, sizeof(noOpData4_proform_studio), QStringLiteral("noOp")); - else if (nordictrack_gx_2_7) { + else if (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci) { innerWriteResistance(); writeCharacteristic(noOpData7, sizeof(noOpData7), QStringLiteral("noOp")); } else if (proform_hybrid_trainer_PFEL03815) { @@ -668,18 +694,23 @@ void proformbike::update() { } else if (proform_bike_sb) { innerWriteResistance(); writeCharacteristic(noOpData7, sizeof(noOpData7), QStringLiteral("noOp")); + } else if(proform_bike_225_csx) { + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("noOp")); } else writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp")); break; case 4: if (proform_studio || proform_tdf_10) writeCharacteristic(noOpData5_proform_studio, sizeof(noOpData5_proform_studio), QStringLiteral("noOp")); - else if (nordictrack_gx_2_7) { + else if (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci) { writeCharacteristic(noOpData5_nordictrack_gx_2_7, sizeof(noOpData5_nordictrack_gx_2_7), QStringLiteral("noOp")); } else if (proform_hybrid_trainer_PFEL03815) { writeCharacteristic(noOpData5_proform_hybrid_trainer_PFEL03815, sizeof(noOpData5_proform_hybrid_trainer_PFEL03815), QStringLiteral("noOp")); + } else if (proform_bike_225_csx) { + writeCharacteristic(noOpData5_proform_bike_225_csx, sizeof(noOpData5_proform_bike_225_csx), + QStringLiteral("noOp")); } else if (proform_bike_sb) writeCharacteristic(noOpData5_proform_bike_sb, sizeof(noOpData5_proform_bike_sb), QStringLiteral("noOp")); @@ -692,9 +723,14 @@ void proformbike::update() { case 5: if (proform_studio || proform_tdf_10) writeCharacteristic(noOpData6_proform_studio, sizeof(noOpData6_proform_studio), QStringLiteral("noOp")); - else if (proform_tour_de_france_clc) + else if (proform_tour_de_france_clc) { writeCharacteristic(noOpData6_proform_tour_de_france_clc, sizeof(noOpData6_proform_tour_de_france_clc), QStringLiteral("noOp")); + } else if (proform_bike_225_csx) { + writeCharacteristic(noOpData6_proform_bike_225_csx, sizeof(noOpData6_proform_bike_225_csx), + QStringLiteral("noOp")); + innerWriteResistance(); + } else if (proform_cycle_trainer_400) writeCharacteristic(noOpData6_proform_cycle_trainer_400, sizeof(noOpData6_proform_cycle_trainer_400), QStringLiteral("noOp")); @@ -728,12 +764,14 @@ void proformbike::update() { counterPoll++; if (counterPoll > 6) { counterPoll = 0; + } else if(counterPoll == 6 && proform_bike_225_csx) { + counterPoll = 0; } 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; - } else if (counterPoll == 5 && (nordictrack_gx_2_7 || proform_hybrid_trainer_PFEL03815 || proform_bike_sb)) { + } else if (counterPoll == 5 && (nordictrack_gx_2_7 || proform_cycle_trainer_300_ci || proform_hybrid_trainer_PFEL03815 || proform_bike_sb)) { counterPoll = 0; } @@ -827,6 +865,7 @@ void proformbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -845,6 +884,7 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte 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(); + bool proform_bike_225_csx = settings.value(QZSettings::proform_bike_225_csx, QZSettings::default_proform_bike_225_csx).toBool(); emit debug(QStringLiteral(" << ") + newValue.toHex(' ')); @@ -867,7 +907,7 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } double incline = @@ -909,7 +949,7 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } double incline = @@ -1025,6 +1065,7 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte } } else if (!nordictrack_gx_2_7) { switch ((uint8_t)newValue.at(11)) { + case 0x00: case 0x02: Resistance = 1; m_pelotonResistance = 10; @@ -1204,7 +1245,7 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } } } @@ -1213,18 +1254,18 @@ void proformbike::characteristicChanged(const QLowEnergyCharacteristic &characte settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 // KCal = (((uint16_t)((uint8_t)newValue.at(15)) << 8) + (uint16_t)((uint8_t) newValue.at(14))); Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (Cadence.value() > 0) { CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) @@ -1270,11 +1311,14 @@ void proformbike::btinit() { settings.value(QZSettings::nordictrack_gx_2_7, QZSettings::default_nordictrack_gx_2_7).toBool(); bool proform_cycle_trainer_400 = settings.value(QZSettings::proform_cycle_trainer_400, QZSettings::default_proform_cycle_trainer_400).toBool(); + bool proform_cycle_trainer_300_ci = + settings.value(QZSettings::proform_cycle_trainer_300_ci, QZSettings::default_proform_cycle_trainer_300_ci).toBool(); bool proform_hybrid_trainer_PFEL03815 = settings .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_225_csx = settings.value(QZSettings::proform_bike_225_csx, QZSettings::default_proform_bike_225_csx).toBool(); if (settings.value(QZSettings::proform_studio, QZSettings::default_proform_studio).toBool()) { @@ -1517,6 +1561,108 @@ void proformbike::btinit() { uint8_t initData12[] = {0xff, 0x08, 0x4a, 0xb6, 0x20, 0x98, 0x02, 0x00, 0x00, 0x93, 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 if (proform_cycle_trainer_300_ci) { + max_resistance = 16; + + uint8_t initData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x07, 0x28, 0x90, 0x07, + 0x01, 0x10, 0xcc, 0x7a, 0x3e, 0xf4, 0xb8, 0x66, 0x3a, 0xf8}; + uint8_t initData11[] = {0x01, 0x12, 0xb4, 0x72, 0x46, 0x1c, 0xf0, 0xbe, 0x92, 0x40, + 0x3c, 0xea, 0xce, 0xa4, 0x88, 0x76, 0x4a, 0x28, 0x04, 0xe2}; + uint8_t initData12[] = {0xff, 0x08, 0xf6, 0xcc, 0xe0, 0x80, 0x02, 0x00, 0x00, 0xb5, + 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); + + uint8_t noOpData0[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData1[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData2[] = {0xff, 0x05, 0x00, 0x80, 0x01, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData3[] = {0xfe, 0x02, 0x19, 0x03}; + uint8_t noOpData4[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x07, 0x15, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData5[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData6[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData7[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x00, 0x0d, 0x00, 0x10, 0x00, 0xc0, 0x1c, 0x4c, 0x00, 0x00, 0xe0}; + uint8_t noOpData8[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x10, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData9[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData11[] = {0xff, 0x05, 0x00, 0x80, 0x01, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData12[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData13[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData14[] = {0xff, 0x05, 0x00, 0x80, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData15[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData16[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x07, 0x13, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData17[] = {0xff, 0x05, 0x00, 0x80, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + writeCharacteristic(noOpData0, sizeof(noOpData0), QStringLiteral("init"), false, false); + 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); + + 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(noOpData7, sizeof(noOpData7), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData8, sizeof(noOpData8), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData9, sizeof(noOpData9), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData10, sizeof(noOpData10), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData11, sizeof(noOpData11), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData12, sizeof(noOpData12), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData13, sizeof(noOpData13), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData14, sizeof(noOpData14), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData15, sizeof(noOpData15), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData16, sizeof(noOpData16), QStringLiteral("init"), false, false); + QThread::msleep(400); + + writeCharacteristic(noOpData17, sizeof(noOpData17), QStringLiteral("init"), false, false); + QThread::msleep(400); + + } else if (proform_bike_225_csx) { + max_resistance = 10; + uint8_t initData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x07, 0x28, 0x90, 0x07, 0x01, 0xd2, 0x74, 0x14, 0xb2, 0x5e, 0x08, 0xa0, 0x5e, 0x0a}; + uint8_t initData11[] = {0x01, 0x12, 0xbc, 0x6c, 0x1a, 0xc6, 0x90, 0x28, 0xe6, 0xa2, 0x64, 0x24, 0xe2, 0xae, 0x98, 0x50, 0x0e, 0xfa, 0xac, 0x9c}; + uint8_t initData12[] = {0xff, 0x08, 0x4a, 0x36, 0x20, 0x98, 0x02, 0x00, 0x00, 0x13, 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); diff --git a/src/proformelliptical.cpp b/src/proformelliptical.cpp index 7c9950057..162b8a2b4 100644 --- a/src/proformelliptical.cpp +++ b/src/proformelliptical.cpp @@ -233,13 +233,9 @@ void proformelliptical::characteristicChanged(const QLowEnergyCharacteristic &ch return; } - double w = (double)(((uint16_t)((uint8_t)newValue.at(13)) << 8) + (uint16_t)((uint8_t)newValue.at(12))); - if(w == 0 && !filterWattHole) { - filterWattHole = true; - qDebug() << QStringLiteral("filtering watt hole"); + if(newValue.at(11) == 0) { + qDebug() << QStringLiteral("filtering resistance hole"); return; - } else if(w > 0) { - filterWattHole = false; } Resistance = GetResistanceFromPacket(newValue); diff --git a/src/proformelliptical.h b/src/proformelliptical.h index 8f955c1c9..1ccfcedde 100644 --- a/src/proformelliptical.h +++ b/src/proformelliptical.h @@ -70,8 +70,6 @@ class proformelliptical : public elliptical { bool noWriteResistance = false; bool noHeartService = false; - bool filterWattHole = false; - #ifdef Q_OS_IOS lockscreen *h = 0; #endif diff --git a/src/proformrower.cpp b/src/proformrower.cpp index 2c6d5613f..c96a63020 100644 --- a/src/proformrower.cpp +++ b/src/proformrower.cpp @@ -478,6 +478,7 @@ double proformrower::GetResistanceFromPacket(QByteArray packet) { } void proformrower::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -492,7 +493,7 @@ 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; + ((double)lastRefreshCharacteristicChanged.msecsTo(now)) / 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))); @@ -518,14 +519,14 @@ void proformrower::characteristicChanged(const QLowEnergyCharacteristic &charact if (watts()) KCal += ((((0.048 * ((double)watts()) + 1.19) * weight * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 // KCal = (((uint16_t)((uint8_t)newValue.at(15)) << 8) + (uint16_t)((uint8_t) newValue.at(14))); // Distance += ((Speed.value() / 3600000.0) * - // ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + // ((double)lastRefreshCharacteristicChanged.msecsTo(now))); Distance = (((uint16_t)(((uint8_t)newValue.at(15)) << 8) + (uint16_t)((uint8_t)newValue.at(14)))) / 1000.0; - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) diff --git a/src/proformtelnetbike.cpp b/src/proformtelnetbike.cpp new file mode 100644 index 000000000..f428f7cd1 --- /dev/null +++ b/src/proformtelnetbike.cpp @@ -0,0 +1,487 @@ +#include "proformtelnetbike.h" +#ifdef Q_OS_ANDROID +#include "keepawakehelper.h" +#endif +#include "virtualbike.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::chrono_literals; + +proformtelnetbike::proformtelnetbike(bool noWriteResistance, bool noHeartService, uint8_t bikeResistanceOffset, + double bikeResistanceGain) { + QSettings settings; + m_watt.setType(metric::METRIC_WATT); + target_watts.setType(metric::METRIC_WATT); + Speed.setType(metric::METRIC_SPEED); + refresh = new QTimer(this); + this->noWriteResistance = noWriteResistance; + this->noHeartService = noHeartService; + this->bikeResistanceGain = bikeResistanceGain; + this->bikeResistanceOffset = bikeResistanceOffset; + initDone = false; + connect(refresh, &QTimer::timeout, this, &proformtelnetbike::update); + refresh->start(200ms); + + bool ok = connect(&telnet, &QTelnet::newData, this, &proformtelnetbike::characteristicChanged); + + ergModeSupported = true; // IMPORTANT, only for this bike + + connectToDevice(); + + initRequest = true; + + // ******************************************* virtual bike init ************************************* + if (!firstStateChanged && !this->hasVirtualDevice() +#ifdef Q_OS_IOS +#ifndef IO_UNDER_QT + && !h +#endif +#endif + ) { + QSettings settings; + bool virtual_device_enabled = + settings.value(QZSettings::virtual_device_enabled, QZSettings::default_virtual_device_enabled).toBool(); +#ifdef Q_OS_IOS +#ifndef IO_UNDER_QT + bool cadence = + settings.value(QZSettings::bike_cadence_sensor, QZSettings::default_bike_cadence_sensor).toBool(); + bool ios_peloton_workaround = + settings.value(QZSettings::ios_peloton_workaround, QZSettings::default_ios_peloton_workaround).toBool(); + if (ios_peloton_workaround && cadence) { + qDebug() << "ios_peloton_workaround activated!"; + h = new lockscreen(); + h->virtualbike_ios(); + } else +#endif +#endif + if (virtual_device_enabled) { + emit debug(QStringLiteral("creating virtual bike interface...")); + auto virtualBike = + new virtualbike(this, noWriteResistance, noHeartService, bikeResistanceOffset, bikeResistanceGain); + // connect(virtualBike,&virtualbike::debug ,this,& proformtelnetbike::debug); + connect(virtualBike, &virtualbike::changeInclination, this, &proformtelnetbike::changeInclination); + this->setVirtualDevice(virtualBike, VIRTUAL_DEVICE_MODE::PRIMARY); + } + } + firstStateChanged = 1; + // ******************************************************************************************************** +} + +void proformtelnetbike::connectToDevice() { + QSettings settings; + // https://github.com/dawsontoth/zwifit/blob/e846501149a6c8fbb03af8d7b9eab20474624883/src/ifit.js + telnet.connectToHost(settings.value(QZSettings::proformtdf1ip, QZSettings::default_proformtdf1ip).toString(), 23); + telnet.waitForConnected(); + telnet.sendData("./utconfig\n"); + QThread::sleep(1); + telnet.sendData("2\n"); // modify variables + +} + +/* +void proformtelnetbike::writeCharacteristic(uint8_t *data, uint8_t data_len, const QString &info, bool disable_log, + bool wait_for_response) { + QEventLoop loop; + QTimer timeout; + if (wait_for_response) { + connect(gattCommunicationChannelService, &QLowEnergyService::characteristicChanged, &loop, &QEventLoop::quit); + timeout.singleShot(300ms, &loop, &QEventLoop::quit); + } else { + connect(gattCommunicationChannelService, &QLowEnergyService::characteristicWritten, &loop, &QEventLoop::quit); + timeout.singleShot(300ms, &loop, &QEventLoop::quit); + } + + gattCommunicationChannelService->writeCharacteristic(gattWriteCharacteristic, + QByteArray((const char *)data, data_len)); + + if (!disable_log) { + emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') + + QStringLiteral(" // ") + info); + } + + loop.exec(); +}*/ + +resistance_t proformtelnetbike::resistanceFromPowerRequest(uint16_t power) { + qDebug() << QStringLiteral("resistanceFromPowerRequest") << Cadence.value(); + + QSettings settings; + + double watt_gain = settings.value(QZSettings::watt_gain, QZSettings::default_watt_gain).toDouble(); + double watt_offset = settings.value(QZSettings::watt_offset, QZSettings::default_watt_offset).toDouble(); + + for (resistance_t i = 1; i < max_resistance; i++) { + if (((wattsFromResistance(i) * watt_gain) + watt_offset) <= power && + ((wattsFromResistance(i + 1) * watt_gain) + watt_offset) >= power) { + qDebug() << QStringLiteral("resistanceFromPowerRequest") + << ((wattsFromResistance(i) * watt_gain) + watt_offset) + << ((wattsFromResistance(i + 1) * watt_gain) + watt_offset) << power; + return i; + } + } + if (power < ((wattsFromResistance(1) * watt_gain) + watt_offset)) + return 1; + else + return max_resistance; +} + +uint16_t proformtelnetbike::wattsFromResistance(resistance_t resistance) { + + if (currentCadence().value() == 0) + return 0; + + switch (resistance) { + case 0: + case 1: + // -13.5 + 0.999x + 0.00993x² + return (-13.5 + (0.999 * currentCadence().value()) + (0.00993 * pow(currentCadence().value(), 2))); + case 2: + // -17.7 + 1.2x + 0.0116x² + return (-17.7 + (1.2 * currentCadence().value()) + (0.0116 * pow(currentCadence().value(), 2))); + + case 3: + // -17.5 + 1.24x + 0.014x² + return (-17.5 + (1.24 * currentCadence().value()) + (0.014 * pow(currentCadence().value(), 2))); + + case 4: + // -20.9 + 1.43x + 0.016x² + return (-20.9 + (1.43 * currentCadence().value()) + (0.016 * pow(currentCadence().value(), 2))); + + case 5: + // -27.9 + 1.75x+0.0172x² + return (-27.9 + (1.75 * currentCadence().value()) + (0.0172 * pow(currentCadence().value(), 2))); + + case 6: + // -26.7 + 1.9x + 0.0201x² + return (-26.7 + (1.9 * currentCadence().value()) + (0.0201 * pow(currentCadence().value(), 2))); + + case 7: + // -33.5 + 2.23x + 0.0225x² + return (-33.5 + (2.23 * currentCadence().value()) + (0.0225 * pow(currentCadence().value(), 2))); + + case 8: + // -36.5+2.5x+0.0262x² + return (-36.5 + (2.5 * currentCadence().value()) + (0.0262 * pow(currentCadence().value(), 2))); + + case 9: + // -38+2.62x+0.0305x² + return (-38.0 + (2.62 * currentCadence().value()) + (0.0305 * pow(currentCadence().value(), 2))); + + case 10: + // -41.2+2.85x+0.0327x² + return (-41.2 + (2.85 * currentCadence().value()) + (0.0327 * pow(currentCadence().value(), 2))); + + case 11: + // -43.4+3.01x+0.0359x² + return (-43.4 + (3.01 * currentCadence().value()) + (0.0359 * pow(currentCadence().value(), 2))); + + case 12: + // -46.8+3.23x+0.0364x² + return (-46.8 + (3.23 * currentCadence().value()) + (0.0364 * pow(currentCadence().value(), 2))); + + case 13: + // -49+3.39x+0.0371x² + return (-49.0 + (3.39 * currentCadence().value()) + (0.0371 * pow(currentCadence().value(), 2))); + + case 14: + // -53.4+3.55x+0.0383x² + return (-53.4 + (3.55 * currentCadence().value()) + (0.0383 * pow(currentCadence().value(), 2))); + + case 15: + // -49.9+3.37x+0.0429x² + return (-49.9 + (3.37 * currentCadence().value()) + (0.0429 * pow(currentCadence().value(), 2))); + + case 16: + default: + // -47.1+3.25x+0.0464x² + return (-47.1 + (3.25 * currentCadence().value()) + (0.0464 * pow(currentCadence().value(), 2))); + } +} + +void proformtelnetbike::sendFrame(QByteArray frame) { + telnet.sendData(frame); + qDebug() << " >> " << frame; +} + +void proformtelnetbike::update() { + qDebug() << "websocket.state()" << telnet.isConnected(); + + if (initRequest) { + initRequest = false; + btinit(); + emit connectedAndDiscovered(); + } else if (telnet.isConnected()) { + update_metrics(false, watts()); + + // updating the treadmill console every second + if (sec1Update++ == (500 / refresh->interval())) { + sec1Update = 0; + // updateDisplay(elapsed); + } + + if (requestStart != -1) { + emit debug(QStringLiteral("starting...")); + + // btinit(); + + requestStart = -1; + emit bikeStarted(); + } + if (requestStop != -1) { + emit debug(QStringLiteral("stopping...")); + // writeCharacteristic(initDataF0C800B8, sizeof(initDataF0C800B8), "stop tape"); + requestStop = -1; + } + } +} + +bool proformtelnetbike::inclinationAvailableByHardware() { return true; } + +resistance_t proformtelnetbike::pelotonToBikeResistance(int pelotonResistance) { + if (pelotonResistance <= 10) { + return 1; + } + if (pelotonResistance <= 20) { + return 2; + } + if (pelotonResistance <= 25) { + return 3; + } + if (pelotonResistance <= 30) { + return 4; + } + if (pelotonResistance <= 35) { + return 5; + } + if (pelotonResistance <= 40) { + return 6; + } + if (pelotonResistance <= 45) { + return 7; + } + if (pelotonResistance <= 50) { + return 8; + } + if (pelotonResistance <= 55) { + return 9; + } + if (pelotonResistance <= 60) { + return 10; + } + if (pelotonResistance <= 65) { + return 11; + } + if (pelotonResistance <= 70) { + return 12; + } + if (pelotonResistance <= 75) { + return 13; + } + if (pelotonResistance <= 80) { + return 14; + } + if (pelotonResistance <= 85) { + return 15; + } + if (pelotonResistance <= 100) { + return 16; + } + return Resistance.value(); +} + +void proformtelnetbike::serviceDiscovered(const QBluetoothUuid &gatt) { + emit debug(QStringLiteral("serviceDiscovered ") + gatt.toString()); +} + +void proformtelnetbike::characteristicChanged(const char *buff, int len) { + // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); + QSettings settings; + QString heartRateBeltName = + settings.value(QZSettings::heart_rate_belt_name, QZSettings::default_heart_rate_belt_name).toString(); + bool disable_hr_frommachinery = + settings.value(QZSettings::heart_ignore_builtin, QZSettings::default_heart_ignore_builtin).toBool(); + bool erg_mode = settings.value(QZSettings::zwift_erg, QZSettings::default_zwift_erg).toBool(); + + QByteArray newValue = QByteArray::fromRawData(buff, len); + emit debug(QStringLiteral(" << ") + newValue); + + if(newValue.contains("Shared Memory Management Utility")) { + emit debug(QStringLiteral("Ready to start the poll")); + sendFrame("2\n"); // current watt + } else if(newValue.contains("Enter New Value")) { + if(poolIndex >= 4) { + if(!erg_mode) { + sendFrame((QString::number(requestInclination) + "\n").toLocal8Bit()); // target incline + qDebug() << "forceInclination" << requestInclination; + requestInclination = -100; + } else { + double r = requestPower; + if (settings.value(QZSettings::watt_gain, QZSettings::default_watt_gain).toDouble() <= 2.00) { + if (settings.value(QZSettings::watt_gain, QZSettings::default_watt_gain).toDouble() != 1.0) { + qDebug() << QStringLiteral("request watt value was ") << r + << QStringLiteral("but it will be transformed to") + << r / settings.value(QZSettings::watt_gain, QZSettings::default_watt_gain).toDouble(); + } + r /= settings.value(QZSettings::watt_gain, QZSettings::default_watt_gain).toDouble(); + } + if (settings.value(QZSettings::watt_offset, QZSettings::default_watt_offset).toDouble() < 0) { + if (settings.value(QZSettings::watt_offset, QZSettings::default_watt_offset).toDouble() != 0.0) { + qDebug() << QStringLiteral("request watt value was ") << r + << QStringLiteral("but it will be transformed to") + << r - settings.value(QZSettings::watt_offset, QZSettings::default_watt_offset).toDouble(); + } + r -= settings.value(QZSettings::watt_offset, QZSettings::default_watt_offset).toDouble(); + } + sendFrame((QString::number(r) + "\n").toLocal8Bit()); // target watt + qDebug() << "forceWatt" << r; + requestPower = -1; + } + poolIndex = 0; + } else { + sendFrame("q\n"); // quit + } + } else if(newValue.contains("Enter Variable Offset")) { + qDebug() << "poolIndex" << poolIndex; + bool done = false; + do { + switch (poolIndex) + { + case 0: + sendFrame("124\n"); // current watt + done = true; + break; + case 1: + sendFrame("40\n"); // current rpm + done = true; + break; + case 2: + sendFrame("34\n"); // current speed + done = true; + break; + case 3: + if(!erg_mode) { + if(requestInclination != -100) { + sendFrame("45\n"); // target incline + done = true; + } + else + poolIndex = 99; + } else { + if(requestPower != -1) { + sendFrame("125\n"); // target watt + done = true; + } + else + poolIndex = 99; + } + break; + default: + break; + } + poolIndex++; + if(poolIndex > 4) + poolIndex = 0; + } while(!done); + } + + QStringList packet = QString::fromLocal8Bit(newValue).split(" "); + qDebug() << packet; + if (newValue.contains("Current Watts")) { + double watt = packet[3].toDouble(); + if (settings.value(QZSettings::power_sensor_name, QZSettings::default_power_sensor_name) + .toString() + .startsWith(QStringLiteral("Disabled"))) + m_watt = watt; + emit debug(QStringLiteral("Current Watt: ") + QString::number(watts())); + } else if (newValue.contains("Cur RPM")) { + double RPM = packet[3].toDouble(); + Cadence = RPM; + emit debug(QStringLiteral("Current Cadence: ") + QString::number(Cadence.value())); + + if (Cadence.value() > 0) { + CrankRevs++; + LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); + } + } else if (newValue.contains("Cur KPH")) { + if (!settings.value(QZSettings::speed_power_based, QZSettings::default_speed_power_based).toBool()) { + double kph = packet[3].toDouble() / 10.0; + Speed = kph; + emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); + } else { + Speed = metric::calculateSpeedFromPower( + watts(), Inclination.value(), Speed.value(), + fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + } + } + + if (watts()) { + KCal += + ((((0.048 * ((double)watts()) + 1.19) * + settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / + 200.0) / + (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( + QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + //* 3.5) / 200 ) / 60 + Distance += ((Speed.value() / (double)3600.0) / + ((double)1000.0 / (double)(lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())))); + } + /* + Resistance = resistance; + m_pelotonResistance = (100 / 32) * Resistance.value(); + emit resistanceRead(Resistance.value()); */ + + /* + if (!disable_hr_frommachinery && !values[QStringLiteral("Chest Pulse")].isUndefined()) { + Heart = values[QStringLiteral("Chest Pulse")].toString().toDouble(); + // index += 1; // NOTE: clang-analyzer-deadcode.DeadStores + emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); + }*/ + +#ifdef Q_OS_ANDROID + if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) + Heart = (uint8_t)KeepAwakeHelper::heart(); + else +#endif + { + if (disable_hr_frommachinery && heartRateBeltName.startsWith(QStringLiteral("Disabled"))) { + update_hr_from_external(); + } + } + + lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + +#ifdef Q_OS_IOS +#ifndef IO_UNDER_QT + bool cadence = settings.value(QZSettings::bike_cadence_sensor, QZSettings::default_bike_cadence_sensor).toBool(); + bool ios_peloton_workaround = + settings.value(QZSettings::ios_peloton_workaround, QZSettings::default_ios_peloton_workaround).toBool(); + if (ios_peloton_workaround && cadence && h && firstStateChanged) { + h->virtualbike_setCadence(currentCrankRevolutions(), lastCrankEventTime()); + h->virtualbike_setHeartRate((uint8_t)metrics_override_heartrate()); + } +#endif +#endif + + /* + emit debug(QStringLiteral("Current Resistance: ") + QString::number(Resistance.value())); + emit debug(QStringLiteral("Current Calculate Distance: ") + QString::number(Distance.value())); + emit debug(QStringLiteral("Current CrankRevs: ") + QString::number(CrankRevs)); + emit debug(QStringLiteral("Last CrankEventTime: ") + QString::number(LastCrankEventTime)); */ +} + +void proformtelnetbike::btinit() { initDone = true; } + +void proformtelnetbike::deviceDiscovered(const QBluetoothDeviceInfo &device) { + emit debug(QStringLiteral("Found new device: ") + device.name() + " (" + device.address().toString() + ')'); +} + +bool proformtelnetbike::connected() { return telnet.isConnected(); } + +uint16_t proformtelnetbike::watts() { return m_watt.value(); } diff --git a/src/proformtelnetbike.h b/src/proformtelnetbike.h new file mode 100644 index 000000000..c62347695 --- /dev/null +++ b/src/proformtelnetbike.h @@ -0,0 +1,110 @@ +#ifndef PROFORMTELNETBIKE_H +#define PROFORMTELNETBIKE_H + + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef Q_OS_ANDROID +#include +#else +#include +#endif +#include +#include +#include +#include + +#include +#include + +#include "bike.h" + +#include "QTelnet.h" + +#ifdef Q_OS_IOS +#include "ios/lockscreen.h" +#endif + +class proformtelnetbike : public bike { + Q_OBJECT + public: + proformtelnetbike(bool noWriteResistance, bool noHeartService, uint8_t bikeResistanceOffset, + double bikeResistanceGain); + resistance_t pelotonToBikeResistance(int pelotonResistance) override; + resistance_t resistanceFromPowerRequest(uint16_t power) override; + resistance_t maxResistance() override { return max_resistance; } + bool inclinationAvailableByHardware() override; + bool connected() override; + + private: + QTelnet telnet; + resistance_t max_resistance = 100; + resistance_t min_resistance = -20; + double max_incline_supported = 20; + void connectToDevice(); + uint16_t wattsFromResistance(resistance_t resistance); + double GetDistanceFromPacket(QByteArray packet); + QTime GetElapsedFromPacket(QByteArray packet); + void btinit(); + void writeCharacteristic(uint8_t *data, uint8_t data_len, const QString &info, bool disable_log = false, + bool wait_for_response = false); + void startDiscover(); + void sendPoll(); + uint16_t watts() override; + void sendFrame(QByteArray frame); + + QTimer *refresh; + uint8_t counterPoll = 0; + uint8_t bikeResistanceOffset = 4; + double bikeResistanceGain = 1.0; + + uint8_t sec1Update = 0; + QString lastPacket; + QDateTime lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + uint8_t firstStateChanged = 0; + metric target_watts; + + bool initDone = false; + bool initRequest = false; + + bool noWriteResistance = false; + bool noHeartService = false; + + uint8_t poolIndex = 0; + +#ifdef Q_OS_IOS + lockscreen *h = 0; +#endif + + signals: + void disconnected(); + void debug(QString string); + + public slots: + void deviceDiscovered(const QBluetoothDeviceInfo &device); + + private slots: + + void characteristicChanged(const char *buff, int len); + + void serviceDiscovered(const QBluetoothUuid &gatt); + void update(); +}; +#endif // PROFORMTELNETBIKE_H diff --git a/src/proformtreadmill.cpp b/src/proformtreadmill.cpp index 0c8626fdb..e9f83b427 100644 --- a/src/proformtreadmill.cpp +++ b/src/proformtreadmill.cpp @@ -72,8 +72,15 @@ void proformtreadmill::forceIncline(double incline) { settings.value(QZSettings::proform_treadmill_se, QZSettings::default_proform_treadmill_se).toBool(); bool norditrack_s25i_treadmill = settings.value(QZSettings::norditrack_s25i_treadmill, QZSettings::default_norditrack_s25i_treadmill).toBool(); + bool norditrack_s25_treadmill = + settings.value(QZSettings::norditrack_s25i_treadmill, QZSettings::default_norditrack_s25_treadmill).toBool(); bool proform_treadmill_z1300i = settings.value(QZSettings::proform_treadmill_z1300i, QZSettings::default_proform_treadmill_z1300i).toBool(); + bool nordictrack_s20_treadmill = settings.value(QZSettings::nordictrack_s20_treadmill, + QZSettings::default_nordictrack_s20_treadmill).toBool(); + bool proform_treadmill_l6_0s = settings.value(QZSettings::proform_treadmill_l6_0s, QZSettings::default_proform_treadmill_l6_0s).toBool(); + bool proform_8_5_treadmill = settings.value(QZSettings::proform_8_5_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); + bool proform_2000_treadmill = settings.value(QZSettings::proform_2000_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); if (proform_treadmill_1800i) { uint8_t i = abs(incline * 10); @@ -94,9 +101,9 @@ void proformtreadmill::forceIncline(double incline) { if (norditrack_s25i_treadmill) { write[14] = write[11] + write[12] + 0x11; - } else if (proform_treadmill_8_0 || proform_treadmill_9_0 || proform_treadmill_se || proform_treadmill_z1300i) { + } else if (proform_treadmill_8_0 || proform_treadmill_9_0 || proform_treadmill_se || proform_treadmill_z1300i || proform_treadmill_l6_0s || norditrack_s25_treadmill || proform_8_5_treadmill || proform_2000_treadmill) { write[14] = write[11] + write[12] + 0x12; - } else if (!nordictrack_t65s_treadmill && !nordictrack_s30_treadmill && !nordictrack_t65s_83_treadmill) { + } else if (!nordictrack_t65s_treadmill && !nordictrack_s30_treadmill && !nordictrack_s20_treadmill && !nordictrack_t65s_83_treadmill) { for (uint8_t i = 0; i < 7; i++) { write[14] += write[i + 6]; } @@ -129,8 +136,15 @@ void proformtreadmill::forceSpeed(double speed) { .toBool(); bool norditrack_s25i_treadmill = settings.value(QZSettings::norditrack_s25i_treadmill, QZSettings::default_norditrack_s25i_treadmill).toBool(); + bool norditrack_s25_treadmill = + settings.value(QZSettings::norditrack_s25i_treadmill, QZSettings::default_norditrack_s25_treadmill).toBool(); bool proform_treadmill_z1300i = settings.value(QZSettings::proform_treadmill_z1300i, QZSettings::default_proform_treadmill_z1300i).toBool(); + bool nordictrack_s20_treadmill = settings.value(QZSettings::nordictrack_s20_treadmill, + QZSettings::default_nordictrack_s20_treadmill).toBool(); + bool proform_treadmill_l6_0s = settings.value(QZSettings::proform_treadmill_l6_0s, QZSettings::default_proform_treadmill_l6_0s).toBool(); + bool proform_8_5_treadmill = settings.value(QZSettings::proform_8_5_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); + bool proform_2000_treadmill = settings.value(QZSettings::proform_2000_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); uint8_t noOpData7[] = {0xfe, 0x02, 0x0d, 0x02}; uint8_t write[] = {0xff, 0x0d, 0x02, 0x04, 0x02, 0x09, 0x04, 0x09, 0x02, 0x01, @@ -142,9 +156,9 @@ void proformtreadmill::forceSpeed(double speed) { if (norditrack_s25i_treadmill) { write[14] = write[11] + write[12] + 0x11; } else if (proform_treadmill_8_0 || proform_treadmill_9_0 || proform_treadmill_se || proform_treadmill_cadence_lt || - proform_treadmill_z1300i) { + proform_treadmill_z1300i || proform_treadmill_l6_0s || norditrack_s25_treadmill || proform_8_5_treadmill || proform_2000_treadmill) { write[14] = write[11] + write[12] + 0x11; - } else if (!nordictrack_t65s_treadmill && !nordictrack_s30_treadmill && !nordictrack_t65s_83_treadmill) { + } else if (!nordictrack_t65s_treadmill && !nordictrack_s30_treadmill && !nordictrack_s20_treadmill && !nordictrack_t65s_83_treadmill) { for (uint8_t i = 0; i < 7; i++) { write[14] += write[i + 6]; } @@ -199,6 +213,9 @@ void proformtreadmill::update() { bool norditrack_s25i_treadmill = settings.value(QZSettings::norditrack_s25i_treadmill, QZSettings::default_norditrack_s25i_treadmill) .toBool(); + bool norditrack_s25_treadmill = + settings.value(QZSettings::norditrack_s25_treadmill, QZSettings::default_norditrack_s25_treadmill) + .toBool(); bool nordictrack_incline_trainer_x7i = settings .value(QZSettings::nordictrack_incline_trainer_x7i, QZSettings::default_nordictrack_incline_trainer_x7i) @@ -207,6 +224,11 @@ void proformtreadmill::update() { settings.value(QZSettings::proform_treadmill_z1300i, QZSettings::default_proform_treadmill_z1300i).toBool(); bool proform_pro_1000_treadmill = settings.value(QZSettings::proform_pro_1000_treadmill, QZSettings::default_proform_pro_1000_treadmill).toBool(); + bool nordictrack_s20_treadmill = settings.value(QZSettings::nordictrack_s20_treadmill, + QZSettings::default_nordictrack_s20_treadmill).toBool(); + bool proform_treadmill_l6_0s = settings.value(QZSettings::proform_treadmill_l6_0s, QZSettings::default_proform_treadmill_l6_0s).toBool(); + bool proform_8_5_treadmill = settings.value(QZSettings::proform_8_5_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); + bool proform_2000_treadmill = settings.value(QZSettings::proform_2000_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); // bool proform_treadmill_995i = settings.value(QZSettings::proform_treadmill_995i, // QZSettings::default_proform_treadmill_995i).toBool(); @@ -407,6 +429,66 @@ void proformtreadmill::update() { if (counterPoll > 5) { counterPoll = 0; } + } else if (proform_2000_treadmill) { + uint8_t noOpData1[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, 0x0d, 0x1b, 0x94, 0x31, 0x00, 0x00, 0x40, 0x50, 0x00, 0x80}; + uint8_t noOpData3[] = {0xff, 0x05, 0x18, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData4[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData5[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, 0x0d, 0x80, 0x0a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData6[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x84, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + switch (counterPoll) { + case 0: + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("noOp")); + break; + case 1: + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("noOp")); + break; + case 2: + writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("noOp")); + if (requestInclination != -100) { + if (requestInclination < 0) + requestInclination = 0; + if (requestInclination != currentInclination().value() && requestInclination >= 0 && + requestInclination <= 15) { + emit debug(QStringLiteral("writing incline ") + QString::number(requestInclination)); + forceIncline(requestInclination); + } + requestInclination = -100; + } + if (requestSpeed != -1) { + if (requestSpeed != currentSpeed().value() && requestSpeed >= 0 && requestSpeed <= 22) { + emit debug(QStringLiteral("writing speed ") + QString::number(requestSpeed)); + forceSpeed(requestSpeed); + } + requestSpeed = -1; + } + break; + case 3: + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp"), true); + break; + case 4: + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("noOp")); + break; + case 5: + writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("noOp")); + if (requestStart != -1) { + emit debug(QStringLiteral("starting...")); + requestStart = -1; + emit tapeStarted(); + } + if (requestStop != -1) { + emit debug(QStringLiteral("stopping...")); + // writeCharacteristic(initDataF0C800B8, sizeof(initDataF0C800B8), "stop tape"); + requestStop = -1; + } + + break; + } + counterPoll++; + if (counterPoll > 5) { + counterPoll = 0; + } } else if (nordictrack10) { uint8_t noOpData1[] = {0xff, 0x05, 0x18, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -542,6 +624,69 @@ void proformtreadmill::update() { if (counterPoll > 5) { counterPoll = 0; } + } else if (proform_8_5_treadmill) { + uint8_t noOpData1[] = {0xfe, 0x02, 0x19, 0x03}; + uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, 0x02, 0x00, 0x0f, 0x80, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData3[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData4[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData5[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, 0x0d, 0x13, 0x96, 0x31, 0x00, 0x00, 0x40, 0x10, 0x00, 0x80}; + uint8_t noOpData6[] = {0xff, 0x05, 0x18, 0x00, 0x00, 0x01, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + switch (counterPoll) { + case 0: + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("noOp")); + break; + case 1: + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("noOp")); + break; + case 2: + writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("noOp"), false, true); + if (requestInclination != -100) { + if (requestInclination < 0) + requestInclination = 0; + if (requestInclination != currentInclination().value() && requestInclination >= 0 && + requestInclination <= 15) { + emit debug(QStringLiteral("writing incline ") + QString::number(requestInclination)); + forceIncline(requestInclination); + } + requestInclination = -100; + } + if (requestSpeed != -1) { + if (requestSpeed != currentSpeed().value() && requestSpeed >= 0 && requestSpeed <= 22) { + emit debug(QStringLiteral("writing speed ") + QString::number(requestSpeed)); + forceSpeed(requestSpeed); + } + requestSpeed = -1; + } + break; + case 3: + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp")); + break; + case 4: + writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("noOp")); + break; + case 5: + writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("noOp")); + + if (requestStart != -1) { + emit debug(QStringLiteral("starting...")); + + // btinit(); + + requestStart = -1; + emit tapeStarted(); + } + if (requestStop != -1) { + emit debug(QStringLiteral("stopping...")); + // writeCharacteristic(initDataF0C800B8, sizeof(initDataF0C800B8), "stop tape"); + requestStop = -1; + } + break; + } + counterPoll++; + if (counterPoll > 5) { + counterPoll = 0; + } } else if (norditrack_s25i_treadmill) { uint8_t noOpData1[] = {0xfe, 0x02, 0x19, 0x03}; uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, 0x02, 0x00, @@ -609,6 +754,164 @@ void proformtreadmill::update() { if (counterPoll > 5) { counterPoll = 0; } + } else if (nordictrack_s20_treadmill) { + uint8_t noOpData1[] = {0xfe, 0x02, 0x19, 0x03}; + uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, 0x02, 0x00, + 0x0f, 0x80, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData3[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x82, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData4[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData5[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, + 0x0d, 0x13, 0x96, 0x31, 0x00, 0x00, 0x40, 0x10, 0x00, 0x80}; + uint8_t noOpData6[] = {0xff, 0x05, 0x18, 0x00, 0x00, 0x01, 0xe9, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + switch (counterPoll) { + case 0: + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("noOp")); + break; + case 1: + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("noOp")); + break; + case 2: + writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("noOp"), false, true); + break; + case 3: + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp")); + break; + case 4: + writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("noOp")); + break; + case 5: + writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("noOp")); + if (requestInclination != -100) { + if (requestInclination < 0) + requestInclination = 0; + if (requestInclination != currentInclination().value() && requestInclination >= 0 && + requestInclination <= 15) { + emit debug(QStringLiteral("writing incline ") + QString::number(requestInclination)); + forceIncline(requestInclination); + } + requestInclination = -100; + } + if (requestSpeed != -1) { + if (requestSpeed != currentSpeed().value() && requestSpeed >= 0 && requestSpeed <= 22) { + emit debug(QStringLiteral("writing speed ") + QString::number(requestSpeed)); + forceSpeed(requestSpeed); + } + requestSpeed = -1; + } + + if (requestStart != -1) { + emit debug(QStringLiteral("starting...")); + + uint8_t start1[] = {0xfe, 0x02, 0x20, 0x03}; + uint8_t start2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x1c, 0x04, 0x1c, 0x02, 0x09, + 0x00, 0x00, 0x40, 0x02, 0x18, 0x40, 0x00, 0x00, 0x80, 0x30}; + uint8_t start3[] = {0xff, 0x0e, 0x2a, 0x00, 0x00, 0xef, 0x1a, 0x58, 0x02, 0x00, + 0xb4, 0x00, 0x58, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}; + uint8_t start4[] = {0xfe, 0x02, 0x11, 0x02}; + uint8_t start5[] = {0xff, 0x11, 0x02, 0x04, 0x02, 0x0d, 0x04, 0x0d, 0x02, 0x02, + 0x03, 0x10, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xd2, 0x00}; + writeCharacteristic(start1, sizeof(start1), QStringLiteral("start1")); + writeCharacteristic(start2, sizeof(start2), QStringLiteral("start2")); + writeCharacteristic(start3, sizeof(start3), QStringLiteral("start3"), false, true); + writeCharacteristic(start4, sizeof(start4), QStringLiteral("start4")); + writeCharacteristic(start5, sizeof(start5), QStringLiteral("start5"), false, true); + + requestStart = -1; + emit tapeStarted(); + } + if (requestStop != -1 || requestPause != -1) { + forceSpeed(0); + + emit debug(QStringLiteral("stopping...")); + requestStop = -1; + requestPause = -1; + } + break; + } + counterPoll++; + if (counterPoll > 5) { + counterPoll = 0; + } + } else if (proform_treadmill_l6_0s) { + uint8_t noOpData1[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, 0x0d, 0x80, 0x0a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData3[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x84, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData4[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData5[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, 0x0d, 0x1b, 0x94, 0x31, 0x00, 0x00, 0x40, 0x50, 0x00, 0x80}; + uint8_t noOpData6[] = {0xff, 0x05, 0x18, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + switch (counterPoll) { + case 0: + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("noOp")); + break; + case 1: + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("noOp")); + break; + case 2: + writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("noOp"), false, true); + break; + case 3: + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp")); + break; + case 4: + writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("noOp")); + break; + case 5: + writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("noOp")); + if (requestInclination != -100) { + if (requestInclination < 0) + requestInclination = 0; + if (requestInclination != currentInclination().value() && requestInclination >= 0 && + requestInclination <= 15) { + emit debug(QStringLiteral("writing incline ") + QString::number(requestInclination)); + forceIncline(requestInclination); + } + requestInclination = -100; + } + if (requestSpeed != -1) { + if (requestSpeed != currentSpeed().value() && requestSpeed >= 0 && requestSpeed <= 22) { + emit debug(QStringLiteral("writing speed ") + QString::number(requestSpeed)); + forceSpeed(requestSpeed); + } + requestSpeed = -1; + } + + if (requestStart != -1) { + emit debug(QStringLiteral("starting...")); + + uint8_t start1[] = {0xfe, 0x02, 0x20, 0x03}; + uint8_t start2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x1c, 0x04, 0x1c, 0x02, 0x09, + 0x00, 0x00, 0x40, 0x02, 0x18, 0x40, 0x00, 0x00, 0x80, 0x30}; + uint8_t start3[] = {0xff, 0x0e, 0x2a, 0x00, 0x00, 0xef, 0x1a, 0x58, 0x02, 0x00, + 0xb4, 0x00, 0x58, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00}; + uint8_t start4[] = {0xfe, 0x02, 0x11, 0x02}; + uint8_t start5[] = {0xff, 0x11, 0x02, 0x04, 0x02, 0x0d, 0x04, 0x0d, 0x02, 0x02, + 0x03, 0x10, 0xa0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xd2, 0x00}; + writeCharacteristic(start1, sizeof(start1), QStringLiteral("start1")); + writeCharacteristic(start2, sizeof(start2), QStringLiteral("start2")); + writeCharacteristic(start3, sizeof(start3), QStringLiteral("start3"), false, true); + writeCharacteristic(start4, sizeof(start4), QStringLiteral("start4")); + writeCharacteristic(start5, sizeof(start5), QStringLiteral("start5"), false, true); + + requestStart = -1; + emit tapeStarted(); + } + if (requestStop != -1 || requestPause != -1) { + forceSpeed(0); + + emit debug(QStringLiteral("stopping...")); + requestStop = -1; + requestPause = -1; + } + break; + } + counterPoll++; + if (counterPoll > 5) { + counterPoll = 0; + } } else if (proform_treadmill_se) { uint8_t noOpData1[] = {0xfe, 0x02, 0x17, 0x03}; uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, @@ -1101,6 +1404,68 @@ void proformtreadmill::update() { if (counterPoll > 5) { counterPoll = 0; } + } else if (norditrack_s25_treadmill) { + uint8_t noOpData1[] = {0xfe, 0x02, 0x19, 0x03}; + uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, 0x02, 0x00, 0x0f, 0x80, 0x0a, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData3[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x85, 0x00, 0x10, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData4[] = {0xfe, 0x02, 0x14, 0x03}; + uint8_t noOpData5[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x10, 0x04, 0x10, 0x02, 0x00, 0x0a, 0x1b, 0x94, 0x30, 0x00, 0x00, 0x40, 0x50, 0x00, 0x80}; + uint8_t noOpData6[] = {0xff, 0x02, 0x18, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + switch (counterPoll) { + case 0: + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("noOp")); + break; + case 1: + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("noOp")); + break; + case 2: + writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("noOp")); + break; + case 3: + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("noOp"), false, true); + break; + case 4: + writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("noOp")); + break; + case 5: + writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("noOp"), false, true); + if (requestInclination != -100) { + if (requestInclination < 0) + requestInclination = 0; + if (requestInclination != currentInclination().value() && requestInclination >= 0 && + requestInclination <= 15) { + emit debug(QStringLiteral("writing incline ") + QString::number(requestInclination)); + forceIncline(requestInclination); + } + requestInclination = -100; + } + if (requestSpeed != -1) { + if (requestSpeed != currentSpeed().value() && requestSpeed >= 0 && requestSpeed <= 22) { + emit debug(QStringLiteral("writing speed ") + QString::number(requestSpeed)); + forceSpeed(requestSpeed); + } + requestSpeed = -1; + } + if (requestStart != -1) { + emit debug(QStringLiteral("starting...")); + + // btinit(); + + requestStart = -1; + emit tapeStarted(); + } + if (requestStop != -1) { + emit debug(QStringLiteral("stopping...")); + // writeCharacteristic(initDataF0C800B8, sizeof(initDataF0C800B8), "stop tape"); + requestStop = -1; + } + break; + } + counterPoll++; + if (counterPoll > 5) { + counterPoll = 0; + } } else { uint8_t noOpData1[] = {0xfe, 0x02, 0x19, 0x03}; uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x07, 0x15, 0x02, 0x00, @@ -1212,6 +1577,10 @@ void proformtreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha .toBool(); bool proform_treadmill_z1300i = settings.value(QZSettings::proform_treadmill_z1300i, QZSettings::default_proform_treadmill_z1300i).toBool(); + bool nordictrack_s20_treadmill = settings.value(QZSettings::nordictrack_s20_treadmill, + QZSettings::default_nordictrack_s20_treadmill).toBool(); + bool proform_8_5_treadmill = settings.value(QZSettings::proform_8_5_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); + bool proform_2000_treadmill = settings.value(QZSettings::proform_2000_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); double weight = settings.value(QZSettings::weight, QZSettings::default_weight).toFloat(); @@ -1226,7 +1595,7 @@ void proformtreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha (newValue.at(4) != 0x02 || (newValue.at(5) != 0x31 && newValue.at(5) != 0x34))) || ((norditrack_s25i_treadmill) && (newValue.at(4) != 0x02 || (newValue.at(5) != 0x2f))) || ((nordictrack_t65s_treadmill || proform_pro_1000_treadmill || nordictrack_t65s_83_treadmill || nordictrack_s30_treadmill || - proform_treadmill_se || proform_cadence_lt) && + nordictrack_s20_treadmill || proform_treadmill_se || proform_cadence_lt || proform_8_5_treadmill) && (newValue.at(4) != 0x02 || newValue.at(5) != 0x2e)) || (((uint8_t)newValue.at(12)) == 0xFF && ((uint8_t)newValue.at(13)) == 0xFF && ((uint8_t)newValue.at(14)) == 0xFF && ((uint8_t)newValue.at(15)) == 0xFF && @@ -1313,6 +1682,8 @@ void proformtreadmill::btinit() { .toBool(); bool norditrack_s25i_treadmill = settings.value(QZSettings::norditrack_s25i_treadmill, QZSettings::default_norditrack_s25i_treadmill).toBool(); + bool norditrack_s25_treadmill = + settings.value(QZSettings::norditrack_s25_treadmill, QZSettings::default_norditrack_s25_treadmill).toBool(); bool nordictrack_t65s_83_treadmill = settings.value(QZSettings::nordictrack_t65s_83_treadmill, QZSettings::default_nordictrack_t65s_83_treadmill) .toBool(); @@ -1323,6 +1694,12 @@ void proformtreadmill::btinit() { settings.value(QZSettings::proform_treadmill_z1300i, QZSettings::default_proform_treadmill_z1300i).toBool(); bool proform_pro_1000_treadmill = settings.value(QZSettings::proform_pro_1000_treadmill, QZSettings::default_proform_pro_1000_treadmill).toBool(); + bool nordictrack_s20_treadmill = settings.value(QZSettings::nordictrack_s20_treadmill, + QZSettings::default_nordictrack_s20_treadmill).toBool(); + bool proform_treadmill_l6_0s = settings.value(QZSettings::proform_treadmill_l6_0s, QZSettings::default_proform_treadmill_l6_0s).toBool(); + bool proform_8_5_treadmill = settings.value(QZSettings::proform_8_5_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); + bool proform_2000_treadmill = settings.value(QZSettings::proform_2000_treadmill, QZSettings::default_proform_8_5_treadmill).toBool(); + // bool proform_treadmill_995i = settings.value(QZSettings::proform_treadmill_995i, // QZSettings::default_proform_treadmill_995i).toBool(); @@ -1480,6 +1857,141 @@ void proformtreadmill::btinit() { QThread::msleep(sleepms); writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("init"), false, false); QThread::msleep(sleepms); + } else if (proform_8_5_treadmill) { + uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData3[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData4[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x80, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData5[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData6[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x88, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData7[] = {0xfe, 0x02, 0x0a, 0x02}; + uint8_t initData8[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x82, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData9[] = {0xfe, 0x02, 0x0a, 0x02}; + uint8_t initData10[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x84, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData11[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData12[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x95, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData13[] = {0xfe, 0x02, 0x2c, 0x04}; + uint8_t initData14[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x04, 0x28, 0x90, 0x07, 0x01, 0x72, 0xf4, 0x74, 0xf2, 0x7e, 0x08, 0x80, 0x1e, 0xaa}; + uint8_t initData15[] = {0x01, 0x12, 0x3c, 0xcc, 0x5a, 0xe6, 0x90, 0x08, 0xa6, 0x42, 0xe4, 0x84, 0x22, 0xce, 0x98, 0x30, 0xce, 0x9a, 0x2c, 0xfc}; + uint8_t initData16[] = {0xff, 0x08, 0x8a, 0x56, 0x20, 0x98, 0x02, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData17[] = {0xfe, 0x02, 0x19, 0x03}; + uint8_t initData18[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, 0x02, 0x00, 0x0f, 0x00, 0x10, 0x00, 0xd8, 0x1c, 0x48, 0x00, 0x00, 0xe0}; + uint8_t initData19[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData2, sizeof(initData2), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData3, sizeof(initData3), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData4, sizeof(initData4), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData5, sizeof(initData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData6, sizeof(initData6), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData7, sizeof(initData7), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData8, sizeof(initData8), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData9, sizeof(initData9), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData10, sizeof(initData10), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData13, sizeof(initData13), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData14, sizeof(initData14), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData15, sizeof(initData15), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData16, sizeof(initData16), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData17, sizeof(initData17), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData18, sizeof(initData18), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData19, sizeof(initData19), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + } else if (proform_2000_treadmill) { + uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic(initData2, sizeof(initData2), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData3[] = {0xfe, 0x02, 0x08, 0x02}; + writeCharacteristic(initData3, sizeof(initData3), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData4[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x80, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic(initData4, sizeof(initData4), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData5[] = {0xfe, 0x02, 0x08, 0x02}; + writeCharacteristic(initData5, sizeof(initData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData6[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x88, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic(initData6, sizeof(initData6), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData7[] = {0xfe, 0x02, 0x0a, 0x02}; + writeCharacteristic(initData7, sizeof(initData7), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData8[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x82, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic(initData8, sizeof(initData8), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData9[] = {0xfe, 0x02, 0x0a, 0x02}; + writeCharacteristic(initData9, sizeof(initData9), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData10[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x84, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic(initData10, sizeof(initData10), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData11[] = {0xfe, 0x02, 0x08, 0x02}; + writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData12[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x95, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData13[] = {0xfe, 0x02, 0x2c, 0x04}; + writeCharacteristic(initData13, sizeof(initData13), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData14[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x04, 0x28, 0x90, 0x04, 0x00, 0xb9, 0xf8, 0x45, 0x80, 0xc9, 0x10, 0x6d, 0xb8, 0x09}; + writeCharacteristic(initData14, sizeof(initData14), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData15[] = {0x01, 0x12, 0x58, 0xa5, 0xf0, 0x59, 0xa0, 0x1d, 0x78, 0xd9, 0x38, 0x85, 0xe0, 0x49, 0xd0, 0x2d, 0xb8, 0x09, 0x98, 0xe5}; + writeCharacteristic(initData15, sizeof(initData15), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData16[] = {0xff, 0x08, 0x70, 0xf9, 0x40, 0x80, 0x02, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic(initData16, sizeof(initData16), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData17[] = {0xfe, 0x02, 0x17, 0x03}; + writeCharacteristic(initData17, sizeof(initData17), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData18[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, 0x0d, 0x00, 0x10, 0x00, 0xd8, 0x1c, 0x48, 0x00, 0x00, 0xe0}; + writeCharacteristic(initData18, sizeof(initData18), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + + uint8_t initData19[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x10, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + writeCharacteristic(initData19, sizeof(initData19), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); } else if (proform_pro_1000_treadmill) { uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, @@ -1549,7 +2061,7 @@ void proformtreadmill::btinit() { writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("init"), false, false); QThread::msleep(sleepms); writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("init"), false, false); - QThread::msleep(sleepms); + QThread::msleep(sleepms); } else if (proform_treadmill_z1300i) { uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, @@ -1704,6 +2216,73 @@ void proformtreadmill::btinit() { QThread::msleep(sleepms); writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("init"), false, false); QThread::msleep(sleepms); + } else if (norditrack_s25_treadmill) { + uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData3[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData4[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x80, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData5[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData6[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x88, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData7[] = {0xfe, 0x02, 0x0a, 0x02}; + uint8_t initData8[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x82, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData9[] = {0xfe, 0x02, 0x0a, 0x02}; + uint8_t initData10[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x84, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData11[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData12[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x95, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData13[] = {0xfe, 0x02, 0x2c, 0x04}; + uint8_t initData14[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x04, 0x28, 0x90, 0x07, 0x01, 0x38, 0xac, 0x12, 0x8e, 0xfc, 0x78, 0xee, 0x6a, 0xd0}; + uint8_t initData15[] = {0x01, 0x12, 0x54, 0xda, 0x56, 0xd4, 0x70, 0xf6, 0x62, 0xe8, 0x9c, 0x02, 0xbe, 0x2c, 0xc8, 0x7e, 0x1a, 0x80, 0x24, 0xca}; + uint8_t initData16[] = {0xff, 0x08, 0x66, 0x04, 0xe0, 0x98, 0x02, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData17[] = {0xfe, 0x02, 0x19, 0x03}; + uint8_t initData18[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, 0x02, 0x00, 0x0f, 0x00, 0x10, 0x00, 0xd8, 0x1c, 0x48, 0x00, 0x00, 0xe0}; + uint8_t initData19[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData2, sizeof(initData2), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData3, sizeof(initData3), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData4, sizeof(initData4), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData5, sizeof(initData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData6, sizeof(initData6), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData5, sizeof(initData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData7, sizeof(initData7), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData8, sizeof(initData8), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData9, sizeof(initData9), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData10, sizeof(initData10), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData13, sizeof(initData13), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData14, sizeof(initData14), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData15, sizeof(initData15), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData16, sizeof(initData16), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData17, sizeof(initData17), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData18, sizeof(initData18), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData19, sizeof(initData19), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); } else if (norditrack_s25i_treadmill) { uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, @@ -2125,6 +2704,78 @@ void proformtreadmill::btinit() { QThread::msleep(sleepms); writeCharacteristic(noOpData10, sizeof(noOpData10), QStringLiteral("init"), false, false); QThread::msleep(sleepms); + } else if (proform_treadmill_l6_0s) { + uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData3[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x80, 0x88, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData4[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x88, 0x90, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData5[] = {0xfe, 0x02, 0x0a, 0x02}; + uint8_t initData6[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x82, 0x00, + 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData7[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x84, 0x00, + 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + 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, 0x04, 0x28, 0x90, 0x04, 0x00, 0xee, 0x44, 0x90, 0xea, 0x42, 0xa8, 0xf4, 0x56, 0xb6}; + uint8_t initData11[] = {0x01, 0x12, 0x2c, 0x88, 0xe2, 0x5a, 0xd0, 0x3c, 0x8e, 0x1e, 0x94, 0xe0, 0x7a, 0xf2, 0x78, 0xc4, 0x46, 0xc6, 0x7c, 0xf8}; + uint8_t initData12[] = {0xff, 0x08, 0x72, 0xea, 0xa0, 0x80, 0x02, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData1[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData2[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, 0x0d, 0x00, 0x10, 0x00, 0xd8, 0x1c, 0x48, 0x00, 0x00, 0xe0}; + uint8_t noOpData3[] = {0xff, 0x05, 0x00, 0x00, 0x00, 0x10, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData4[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData5[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData6[] = {0xff, 0x05, 0x00, 0x80, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData2, sizeof(initData2), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData3, sizeof(initData3), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData4, sizeof(initData4), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData5, sizeof(initData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData6, sizeof(initData6), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData5, sizeof(initData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData7, sizeof(initData7), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData8, sizeof(initData8), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData9, sizeof(initData9), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData10, sizeof(initData10), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); } else if (nordictrack_t65s_treadmill) { uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, @@ -2416,6 +3067,90 @@ void proformtreadmill::btinit() { QThread::msleep(sleepms); writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("init"), false, false); QThread::msleep(sleepms); + } else if (nordictrack_s20_treadmill) { + uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; + uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData3[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x80, 0x88, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData4[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x04, 0x04, 0x88, 0x90, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData5[] = {0xfe, 0x02, 0x0a, 0x02}; + uint8_t initData6[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x82, 0x00, + 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t initData7[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x84, 0x00, + 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + 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, 0x04, 0x28, + 0x90, 0x07, 0x01, 0x3b, 0xa0, 0x17, 0x84, 0xf3, + 0x60, 0xd7, 0x5c, 0xdb}; + uint8_t initData11[] = {0x01, 0x12, 0x40, 0xc7, 0x44, 0xc3, 0x40, 0xc7, + 0x4c, 0xfb, 0x60, 0x17, 0x84, 0x33, 0xa0, 0x57, + 0xfc, 0x9b, 0x00, 0xa7}; + uint8_t initData12[] = {0xff, 0x08, 0x44, 0xe3, 0x80, 0x88, 0x02, 0x00, + 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData1[] = {0xfe, 0x02, 0x19, 0x03}; + uint8_t noOpData2[] = { 0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, + 0x02, 0x00, 0x0f, 0x00, 0x10, 0x00, 0xd8, 0x1c, + 0x48, 0x00, 0x00, 0xe0}; + uint8_t noOpData3[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, + 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData4[] = {0xfe, 0x02, 0x17, 0x03}; + uint8_t noOpData5[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t noOpData6[] = {0xff, 0x05, 0x00, 0x80, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData2, sizeof(initData2), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData3, sizeof(initData3), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData4, sizeof(initData4), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData5, sizeof(initData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData6, sizeof(initData6), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData5, sizeof(initData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData7, sizeof(initData7), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData8, sizeof(initData8), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData9, sizeof(initData9), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData10, sizeof(initData10), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData11, sizeof(initData11), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(initData12, sizeof(initData12), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData2, sizeof(noOpData2), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData3, sizeof(noOpData3), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData4, sizeof(noOpData4), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData5, sizeof(noOpData5), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData6, sizeof(noOpData6), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); + writeCharacteristic(noOpData1, sizeof(noOpData1), QStringLiteral("init"), false, false); + QThread::msleep(sleepms); } else if (nordictrack_s30_treadmill) { uint8_t initData1[] = {0xfe, 0x02, 0x08, 0x02}; uint8_t initData2[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x81, 0x87, @@ -2591,14 +3326,14 @@ void proformtreadmill::stateChanged(QLowEnergyService::ServiceState state) { .toBool(); if (virtual_device_enabled) { if (!virtual_device_force_bike) { - debug("creating virtual treadmill interface..."); + emit debug("creating virtual treadmill interface..."); auto virtualTreadmill = new virtualtreadmill(this, noHeartService); connect(virtualTreadmill, &virtualtreadmill::debug, this, &proformtreadmill::debug); connect(virtualTreadmill, &virtualtreadmill::changeInclination, this, &proformtreadmill::changeInclinationRequested); this->setVirtualDevice(virtualTreadmill, VIRTUAL_DEVICE_MODE::PRIMARY); } else { - debug("creating virtual bike interface..."); + emit debug("creating virtual bike interface..."); auto virtualBike = new virtualbike(this); connect(virtualBike, &virtualbike::changeInclination, this, &proformtreadmill::changeInclinationRequested); diff --git a/src/qdomyos-zwift.pri b/src/qdomyos-zwift.pri index ec41c834e..28334c405 100644 --- a/src/qdomyos-zwift.pri +++ b/src/qdomyos-zwift.pri @@ -72,10 +72,13 @@ DEFINES += QT_DEPRECATED_WARNINGS IO_UNDER_QT SMTP_BUILD NOMINMAX # include(../qtzeroconf/qtzeroconf.pri) SOURCES += \ + $$PWD/QTelnet.cpp \ $$PWD/bkoolbike.cpp \ $$PWD/csafe.cpp \ $$PWD/csaferower.cpp \ + $$PWD/eliteariafan.cpp \ $$PWD/fakerower.cpp \ + $$PWD/proformtelnetbike.cpp \ $$PWD/virtualdevice.cpp \ $$PWD/androidactivityresultreceiver.cpp \ $$PWD/androidadblog.cpp \ @@ -280,11 +283,16 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin INCLUDEPATH += fit-sdk/ HEADERS += \ + $$PWD/QTelnet.h \ $$PWD/bkoolbike.h \ $$PWD/csafe.h \ $$PWD/csaferower.h \ + $$PWD/eliteariafan.h \ + $$PWD/proformtelnetbike.h \ $$PWD/windows_zwift_workout_paddleocr_thread.h \ $$PWD/fakerower.h \ + $$PWD/zwift-api/PlayerStateWrapper.h \ + $$PWD/zwift-api/zwift_client_auth.h \ virtualdevice.h \ $$PWD/androidactivityresultreceiver.h \ $$PWD/androidadblog.h \ @@ -714,6 +722,7 @@ DISTFILES += \ $$PWD/android/libs/connectiq-mobile-sdk-android-1.5.aar \ $$PWD/android/res/xml/device_filter.xml \ $$PWD/android/src/CSafeRowerUSBHID.java \ + $$PWD/android/src/ContentHelper.java \ $$PWD/android/src/Garmin.java \ $$PWD/android/src/HidBridge.java \ $$PWD/android/src/IQMessageReceiverWrapper.java \ @@ -722,6 +731,8 @@ DISTFILES += \ $$PWD/android/src/ScreenCaptureService.java \ $$PWD/android/src/WearableController.java \ $$PWD/android/src/WearableMessageListenerService.java \ + $$PWD/android/src/ZwiftAPI.java \ + $$PWD/android/src/main/proto/zwift_messages.proto \ .clang-format \ AppxManifest.xml \ android/AndroidManifest.xml \ @@ -785,6 +796,7 @@ ios { ios { OBJECTIVE_SOURCES += ios/lockscreen.mm \ + ios/ios_eliteariafan.mm \ ios/ios_app_delegate.mm \ fit-sdk/FitDecode.mm \ fit-sdk/FitDeveloperField.mm \ @@ -815,4 +827,4 @@ INCLUDEPATH += purchasing/inapp WINRT_MANIFEST = AppxManifest.xml -VERSION = 2.16.24 +VERSION = 2.16.32 diff --git a/src/qfit.cpp b/src/qfit.cpp index eeb81e678..5755b37a5 100644 --- a/src/qfit.cpp +++ b/src/qfit.cpp @@ -335,6 +335,7 @@ void qfit::save(const QString &filename, QList session, bluetoothde } } + lapMesg.SetTotalDistance((session.last().distance - lastLapOdometer) * 1000.0); // meters lapMesg.SetTotalElapsedTime(session.last().elapsedTime - lastLapTimer); lapMesg.SetTotalTimerTime(session.last().elapsedTime - lastLapTimer); lapMesg.SetEvent(FIT_EVENT_LAP); diff --git a/src/qthttpserver b/src/qthttpserver new file mode 160000 index 000000000..983e93c3b --- /dev/null +++ b/src/qthttpserver @@ -0,0 +1 @@ +Subproject commit 983e93c3b160c62e60b1755d075e959d4685d949 diff --git a/src/qzsettings.cpp b/src/qzsettings.cpp index 9c3bf6302..691fee935 100644 --- a/src/qzsettings.cpp +++ b/src/qzsettings.cpp @@ -680,8 +680,28 @@ const QString QZSettings::proform_pro_1000_treadmill = QStringLiteral("proform_p const QString QZSettings::saris_trainer = QStringLiteral("saris_trainer"); const QString QZSettings::proform_studio_NTEX71021 = QStringLiteral("proform_studio_NTEX71021"); const QString QZSettings::nordictrack_x22i = QStringLiteral("nordictrack_x22i"); +const QString QZSettings::iconsole_elliptical = QStringLiteral("iconsole_elliptical"); +const QString QZSettings::autolap_distance = QStringLiteral("autolap_distance"); +const QString QZSettings::nordictrack_s20_treadmill = QStringLiteral("nordictrack_s20_treadmill"); +const QString QZSettings::freemotion_coachbike_b22_7 = QStringLiteral("freemotion_coachbike_b22_7"); +const QString QZSettings::proform_cycle_trainer_300_ci = QStringLiteral("proform_cycle_trainer_300_ci"); +const QString QZSettings::kingsmith_encrypt_g1_walking_pad = QStringLiteral("kingsmith_encrypt_g1_walking_pad"); +const QString QZSettings::proformtdf1ip = QStringLiteral("proformtdf1ip"); +const QString QZSettings::default_proformtdf1ip = QStringLiteral(""); +const QString QZSettings::proform_bike_225_csx = QStringLiteral("proform_bike_225_csx"); +const QString QZSettings::proform_treadmill_l6_0s = QStringLiteral("proform_treadmill_l6_0s"); +const QString QZSettings::zwift_username = QStringLiteral("zwift_username"); +const QString QZSettings::default_zwift_username = QStringLiteral(""); +const QString QZSettings::zwift_password = QStringLiteral("zwift_password"); +const QString QZSettings::default_zwift_password = QStringLiteral(""); +const QString QZSettings::garmin_bluetooth_compatibility = QStringLiteral("garmin_bluetooth_compatibility"); +const QString QZSettings::norditrack_s25_treadmill = QStringLiteral("norditrack_s25_treadmill"); +const QString QZSettings::proform_8_5_treadmill = QStringLiteral("proform_8_5_treadmill"); +const QString QZSettings::treadmill_incline_min = QStringLiteral("treadmill_incline_min"); +const QString QZSettings::treadmill_incline_max = QStringLiteral("treadmill_incline_max"); +const QString QZSettings::proform_2000_treadmill = QStringLiteral("proform_2000_treadmill"); -const uint32_t allSettingsCount = 570; +const uint32_t allSettingsCount = 587; QVariant allSettings[allSettingsCount][2] = { {QZSettings::cryptoKeySettingsProfiles, QZSettings::default_cryptoKeySettingsProfiles}, @@ -1258,6 +1278,23 @@ QVariant allSettings[allSettingsCount][2] = { {QZSettings::saris_trainer, QZSettings::default_saris_trainer}, {QZSettings::proform_studio_NTEX71021, QZSettings::default_proform_studio_NTEX71021}, {QZSettings::nordictrack_x22i, QZSettings::default_nordictrack_x22i}, + {QZSettings::iconsole_elliptical, QZSettings::default_iconsole_elliptical}, + {QZSettings::autolap_distance, QZSettings::default_autolap_distance}, + {QZSettings::nordictrack_s20_treadmill, QZSettings::default_nordictrack_s20_treadmill}, + {QZSettings::freemotion_coachbike_b22_7, QZSettings::default_freemotion_coachbike_b22_7}, + {QZSettings::proform_cycle_trainer_300_ci, QZSettings::default_proform_cycle_trainer_300_ci}, + {QZSettings::kingsmith_encrypt_g1_walking_pad, QZSettings::default_kingsmith_encrypt_g1_walking_pad}, + {QZSettings::proform_bike_225_csx, QZSettings::default_proform_bike_225_csx}, + {QZSettings::proform_treadmill_l6_0s, QZSettings::default_proform_treadmill_l6_0s}, + {QZSettings::proformtdf1ip, QZSettings::default_proformtdf1ip}, + {QZSettings::zwift_username, QZSettings::default_zwift_username}, + {QZSettings::zwift_password, QZSettings::default_zwift_password}, + {QZSettings::garmin_bluetooth_compatibility, QZSettings::default_garmin_bluetooth_compatibility}, + {QZSettings::norditrack_s25_treadmill, QZSettings::default_norditrack_s25_treadmill}, + {QZSettings::proform_8_5_treadmill, QZSettings::default_proform_8_5_treadmill}, + {QZSettings::treadmill_incline_min, QZSettings::default_treadmill_incline_min}, + {QZSettings::treadmill_incline_max, QZSettings::default_treadmill_incline_max}, + {QZSettings::proform_2000_treadmill, QZSettings::default_proform_2000_treadmill}, }; void QZSettings::qDebugAllSettings(bool showDefaults) { diff --git a/src/qzsettings.h b/src/qzsettings.h index 9ba186d27..f2709003b 100644 --- a/src/qzsettings.h +++ b/src/qzsettings.h @@ -1911,6 +1911,57 @@ class QZSettings { static const QString nordictrack_x22i; static constexpr bool default_nordictrack_x22i = false; + static const QString iconsole_elliptical; + static constexpr bool default_iconsole_elliptical = false; + + static const QString autolap_distance; + static constexpr float default_autolap_distance = 0; + + static const QString nordictrack_s20_treadmill; + static constexpr bool default_nordictrack_s20_treadmill = false; + + static const QString freemotion_coachbike_b22_7; + static constexpr bool default_freemotion_coachbike_b22_7 = false; + + static const QString proform_cycle_trainer_300_ci; + static constexpr bool default_proform_cycle_trainer_300_ci = false; + + static const QString kingsmith_encrypt_g1_walking_pad; + static constexpr bool default_kingsmith_encrypt_g1_walking_pad = false; + + static const QString proform_bike_225_csx; + static constexpr bool default_proform_bike_225_csx = false; + + static const QString proform_treadmill_l6_0s; + static constexpr bool default_proform_treadmill_l6_0s = false; + + static const QString proformtdf1ip; + static const QString default_proformtdf1ip; + + static const QString zwift_username; + static const QString default_zwift_username; + + static const QString zwift_password; + static const QString default_zwift_password; + + static const QString garmin_bluetooth_compatibility; + static constexpr bool default_garmin_bluetooth_compatibility = false; + + static const QString norditrack_s25_treadmill; + static constexpr int default_norditrack_s25_treadmill = false; + + static const QString proform_8_5_treadmill; + static constexpr int default_proform_8_5_treadmill = false; + + static const QString treadmill_incline_min; + static constexpr float default_treadmill_incline_min = -100.0; + + static const QString treadmill_incline_max; + static constexpr float default_treadmill_incline_max = 100.0; + + static const QString proform_2000_treadmill; + static constexpr int default_proform_2000_treadmill = 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. diff --git a/src/renphobike.cpp b/src/renphobike.cpp index b01c2a675..64a39409a 100644 --- a/src/renphobike.cpp +++ b/src/renphobike.cpp @@ -175,6 +175,7 @@ void renphobike::update() { void renphobike::serviceDiscovered(const QBluetoothUuid &gatt) { debug("serviceDiscovered " + gatt.toString()); } void renphobike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -225,7 +226,7 @@ void renphobike::characteristicChanged(const QLowEnergyCharacteristic &character else Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); index += 2; debug("Current Speed: " + QString::number(Speed.value())); } @@ -267,7 +268,7 @@ void renphobike::characteristicChanged(const QLowEnergyCharacteristic &character index += 3; } else { Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); } debug("Current Distance: " + QString::number(Distance.value())); @@ -320,7 +321,7 @@ void renphobike::characteristicChanged(const QLowEnergyCharacteristic &character settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -333,7 +334,7 @@ void renphobike::characteristicChanged(const QLowEnergyCharacteristic &character #endif { if (Flags.heartRate) { - Heart = ((double)((newValue.at(index)))); + Heart = ((double)(((uint8_t)newValue.at(index)))); index += 1; debug("Current Heart: " + QString::number(Heart.value())); } @@ -356,7 +357,7 @@ void renphobike::characteristicChanged(const QLowEnergyCharacteristic &character LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (heartRateBeltName.startsWith("Disabled")) { update_hr_from_external(); diff --git a/src/rower.cpp b/src/rower.cpp index 44e6d38ca..02b0cc42e 100644 --- a/src/rower.cpp +++ b/src/rower.cpp @@ -53,6 +53,7 @@ void rower::clearStats() { Speed.clear(false); KCal.clear(true); Distance.clear(true); + Distance1s.clear(true); Heart.clear(false); m_jouls.clear(true); elevationAcc = 0; @@ -81,6 +82,7 @@ void rower::setPaused(bool p) { Speed.setPaused(p); KCal.setPaused(p); Distance.setPaused(p); + Distance1s.setPaused(p); Heart.setPaused(p); m_jouls.setPaused(p); m_watt.setPaused(p); @@ -104,6 +106,7 @@ void rower::setLap() { Speed.setLap(false); KCal.setLap(true); Distance.setLap(true); + Distance1s.setLap(true); Heart.setLap(false); m_jouls.setLap(true); m_watt.setLap(false); diff --git a/src/schwinn170bike.cpp b/src/schwinn170bike.cpp index e4a109c20..ab00311eb 100644 --- a/src/schwinn170bike.cpp +++ b/src/schwinn170bike.cpp @@ -115,6 +115,7 @@ void schwinn170bike::serviceDiscovered(const QBluetoothUuid &gatt) { } void schwinn170bike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); double heart = 0.0; // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); @@ -140,6 +141,19 @@ void schwinn170bike::characteristicChanged(const QLowEnergyCharacteristic &chara m_watt = ((double)(((uint16_t)((uint8_t)newValue.at(7)) << 8) | (uint16_t)((uint8_t)newValue.at(6)))) / 100.0; emit debug(QStringLiteral("Current Watt: ") + QString::number(m_watt.value())); + double cadence_gain = settings.value(QZSettings::cadence_gain, QZSettings::default_cadence_gain).toDouble(); + double cadence_offset = settings.value(QZSettings::cadence_offset, QZSettings::default_cadence_offset).toDouble(); + + if (settings.value(QZSettings::cadence_sensor_name, QZSettings::default_cadence_sensor_name) + .toString() + .startsWith(QStringLiteral("Disabled"))) { + double c = ((double)(((uint16_t)((uint8_t)newValue.at(4)) << 8) | (uint16_t)((uint8_t)newValue.at(3)))) / 17.47; + if (c > 0) + Cadence = (c * cadence_gain) + cadence_offset; + else + Cadence = 0; + } + emit debug(QStringLiteral("Current Cadence: ") + QString::number(Cadence.value())); if (!settings.value(QZSettings::speed_power_based, QZSettings::default_speed_power_based).toBool()) { @@ -147,12 +161,12 @@ void schwinn170bike::characteristicChanged(const QLowEnergyCharacteristic &chara } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); @@ -161,7 +175,7 @@ void schwinn170bike::characteristicChanged(const QLowEnergyCharacteristic &chara settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); @@ -218,7 +232,7 @@ void schwinn170bike::characteristicChanged(const QLowEnergyCharacteristic &chara qDebug() << QStringLiteral("resistance not updated cause to schwinn_resistance_smooth setting"); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) { if (heart == 0.0) { diff --git a/src/schwinnic4bike.cpp b/src/schwinnic4bike.cpp index 6166496bb..fd1a5ce9e 100644 --- a/src/schwinnic4bike.cpp +++ b/src/schwinnic4bike.cpp @@ -116,6 +116,7 @@ void schwinnic4bike::serviceDiscovered(const QBluetoothUuid &gatt) { } void schwinnic4bike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); double heart = 0.0; // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); @@ -166,7 +167,7 @@ void schwinnic4bike::characteristicChanged(const QLowEnergyCharacteristic &chara } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } index += 2; emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); @@ -208,7 +209,7 @@ void schwinnic4bike::characteristicChanged(const QLowEnergyCharacteristic &chara index += 3; } else { Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); } emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); @@ -256,7 +257,7 @@ void schwinnic4bike::characteristicChanged(const QLowEnergyCharacteristic &chara settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -347,7 +348,7 @@ void schwinnic4bike::characteristicChanged(const QLowEnergyCharacteristic &chara } emit resistanceRead(Resistance.value()); - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) { if (heart == 0.0) { diff --git a/src/settings.qml b/src/settings.qml index caf8b1a67..46a7af886 100644 --- a/src/settings.qml +++ b/src/settings.qml @@ -842,6 +842,35 @@ import QtQuick.Dialogs 1.0 // from version 2.16.23 property bool proform_studio_NTEX71021: false property bool nordictrack_x22i: false + + // from version 2.16.25 + property bool iconsole_elliptical: false + property real autolap_distance: 0 + property bool nordictrack_s20_treadmill: false + + // from version 2.16.28 + property bool freemotion_coachbike_b22_7: false + + // from version 2.16.29 + property bool proform_cycle_trainer_300_ci: false + property bool kingsmith_encrypt_g1_walking_pad: false + property bool proform_bike_225_csx: false + + // from version 2.16.30 + property bool proform_treadmill_l6_0s: false + property string proformtdf1ip: "" + property string zwift_username: "" + property string zwift_password: "" + + // from version 2.16.31 + property bool garmin_bluetooth_compatibility: false + property bool norditrack_s25_treadmill: false + property bool proform_8_5_treadmill: false + property real treadmill_incline_min: -100 + property real treadmill_incline_max: 100 + + // from version 2.16.32 + property bool proform_2000_treadmill: false } function paddingZeros(text, limit) { @@ -2911,6 +2940,19 @@ import QtQuick.Dialogs 1.0 Layout.fillWidth: true onClicked: { settings.proform_studio_NTEX71021 = checked; window.settings_restart_to_apply = true; } } + SwitchDelegate { + text: qsTr("Freemotion Coachbike B22.7") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.freemotion_coachbike_b22_7 + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.freemotion_coachbike_b22_7 = checked; window.settings_restart_to_apply = true; } + } SwitchDelegate { id: proformTDF10odelegate text: qsTr("Proform TDF 1.0") @@ -2966,6 +3008,19 @@ import QtQuick.Dialogs 1.0 Layout.fillWidth: true onClicked: settings.proform_tdf_jonseed_watt = checked } + SwitchDelegate { + text: qsTr("Cycle Trainer 300 CI") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.proform_cycle_trainer_300_ci + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.proform_cycle_trainer_300_ci = checked; window.settings_restart_to_apply = true; } + } SwitchDelegate { id: proformCycleTrainerdelegate text: qsTr("Cycle Trainer 400") @@ -2979,7 +3034,20 @@ import QtQuick.Dialogs 1.0 Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillWidth: true onClicked: { settings.proform_cycle_trainer_400 = checked; window.settings_restart_to_apply = true; } - } + } + SwitchDelegate { + text: qsTr("Proform 225 CSX") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.proform_bike_225_csx + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.proform_bike_225_csx = checked; window.settings_restart_to_apply = true; } + } SwitchDelegate { text: qsTr("Proform SB") spacing: 0 @@ -2994,6 +3062,29 @@ import QtQuick.Dialogs 1.0 onClicked: { settings.proform_bike_sb = checked; window.settings_restart_to_apply = true; } } + RowLayout { + spacing: 10 + Label { + text: qsTr("TDF1 IP:") + Layout.fillWidth: true + } + TextField { + id: proformTDF1IPTextField + text: settings.proformtdf1ip + horizontalAlignment: Text.AlignRight + Layout.fillHeight: false + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + //inputMethodHints: Qt.ImhFormattedNumbersOnly + onAccepted: settings.proformtdf1ip = text + onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length + } + Button { + text: "OK" + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onClicked: { settings.proformtdf1ip = proformTDF1IPTextField.text; window.settings_restart_to_apply = true; toast.show("Setting saved!"); } + } + } + RowLayout { spacing: 10 Label { @@ -4337,7 +4428,6 @@ import QtQuick.Dialogs 1.0 } AccordionElement { - visible: OS_VERSION === "Other" title: qsTr("Zwift Options") + "\uD83E\uDD47" indicatRectColor: Material.color(Material.Grey) textColor: Material.color(Material.Grey) @@ -4345,6 +4435,84 @@ import QtQuick.Dialogs 1.0 accordionContent: ColumnLayout { spacing: 0 + RowLayout { + spacing: 10 + Label { + text: qsTr("Username:") + Layout.fillWidth: true + } + TextField { + id: zwiftUsernameTextField + text: settings.zwift_username + horizontalAlignment: Text.AlignRight + Layout.fillHeight: false + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onAccepted: settings.zwift_username = text + onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length + } + Button { + id: okZwiftUsernameButton + text: "OK" + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onClicked: { settings.zwift_username = zwiftUsernameTextField.text; window.settings_restart_to_apply = true; toast.show("Setting saved!"); } + } + } + + + Label { + text: qsTr("Enter the email address you use to login to Zwift. Ensure there are no spaces before or after your email. Click OK.") + font.bold: true + font.italic: true + font.pixelSize: 9 + textFormat: Text.PlainText + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + color: Material.color(Material.Lime) + } + + RowLayout { + spacing: 10 + Label { + id: labelZwiftPassword + //text: qsTr("Password:") + ((rootItem.zwiftLogin===-1)?"":(rootItem.zwiftLogin===1?"\u2705":"\u274c")) + text: qsTr("Password:") + Layout.fillWidth: true + } + TextField { + id: zwiftPasswordTextField + text: settings.zwift_password + horizontalAlignment: Text.AlignRight + Layout.fillHeight: false + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + inputMethodHints: Qt.ImhHiddenText + echoMode: TextInput.PasswordEchoOnEdit + onAccepted: settings.zwift_password = text + onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length + } + Button { + id: okZwiftPasswordButton + text: "OK" + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onClicked: { settings.zwift_password = zwiftPasswordTextField.text; window.settings_restart_to_apply = true; toast.show("Setting saved!"); } + } + } + + Label { + //text: qsTr("Enter the password you use to login to Zwift. Click OK. If you have entered the correct login credentials and the QZ is able to access your account, you will see a when you reopen QZ. This is a secure login, not accessible by anyone but you.") + text: qsTr("Enter the password you use to login to Zwift. Click OK.") + font.bold: true + font.italic: true + font.pixelSize: 9 + textFormat: Text.PlainText + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + color: Material.color(Material.Lime) + } + SwitchDelegate { text: qsTr("Zwift Treadmill Auto Inclination") spacing: 0 @@ -4416,13 +4584,40 @@ import QtQuick.Dialogs 1.0 } AccordionElement { - title: qsTr("Garmin Companion Options") + "\uD83E\uDD47" + title: qsTr("Garmin Options") + "\uD83E\uDD47" indicatRectColor: Material.color(Material.Grey) textColor: Material.color(Material.Grey) color: Material.backgroundColor accordionContent: ColumnLayout { spacing: 0 + SwitchDelegate { + text: qsTr("Garmin Bluetooth Sensor") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.garmin_bluetooth_compatibility + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.garmin_bluetooth_compatibility = checked; window.settings_restart_to_apply = true; } + } + + Label { + text: qsTr("If you want to send metrics to your Garmin device from your Mac, enable this. Otherwise leave it disabled.") + font.bold: true + font.italic: true + font.pixelSize: 9 + textFormat: Text.PlainText + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + color: Material.color(Material.Lime) + } + SwitchDelegate { text: qsTr("Enable Companion App") spacing: 0 @@ -5236,6 +5431,78 @@ import QtQuick.Dialogs 1.0 color: Material.color(Material.Lime) } + RowLayout { + spacing: 10 + Label { + text: qsTr("Min. Inclination:") + Layout.fillWidth: true + } + TextField { + id: treadmillInclinationMinTextField + text: settings.treadmill_incline_min + horizontalAlignment: Text.AlignRight + Layout.fillHeight: false + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + //inputMethodHints: Qt.ImhDigitsOnly + onAccepted: settings.treadmill_incline_min = text + onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length + } + Button { + text: "OK" + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onClicked: { settings.treadmill_incline_min = treadmillInclinationMinTextField.text; toast.show("Setting saved!"); } + } + } + + Label { + text: qsTr("This overrides the minimum inclination value of your treadmill (in order to reduce the inclination movement). Default is -100") + font.bold: true + font.italic: true + font.pixelSize: 9 + textFormat: Text.PlainText + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + color: Material.color(Material.Lime) + } + + RowLayout { + spacing: 10 + Label { + text: qsTr("Max. Inclination:") + Layout.fillWidth: true + } + TextField { + id: treadmillInclinationMaxTextField + text: settings.treadmill_incline_max + horizontalAlignment: Text.AlignRight + Layout.fillHeight: false + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + //inputMethodHints: Qt.ImhDigitsOnly + onAccepted: settings.treadmill_incline_max = text + onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length + } + Button { + text: "OK" + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onClicked: { settings.treadmill_incline_max = treadmillInclinationMaxTextField.text; toast.show("Setting saved!"); } + } + } + + Label { + text: qsTr("This overrides the maximum inclination value of your treadmill (in order to reduce the inclination movement). Default is -100") + font.bold: true + font.italic: true + font.pixelSize: 9 + textFormat: Text.PlainText + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + color: Material.color(Material.Lime) + } + NewPageElement { title: qsTr("Inclination Overrides") indicatRectColor: Material.color(Material.Grey) @@ -5343,7 +5610,21 @@ import QtQuick.Dialogs 1.0 textColor: Material.color(Material.Yellow) color: Material.backgroundColor accordionContent: ColumnLayout { - spacing: 0 + spacing: 0 + SwitchDelegate { + text: qsTr("Nordictrack S25") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.norditrack_s25_treadmill + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.norditrack_s25_treadmill = checked; window.settings_restart_to_apply = true; } + } + SwitchDelegate { id: nordictrackS25iDelegate text: qsTr("Nordictrack S25i") @@ -5397,7 +5678,33 @@ import QtQuick.Dialogs 1.0 Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillWidth: true onClicked: {settings.nordictrack_10_treadmill = checked; window.settings_restart_to_apply = true; } - } + } + SwitchDelegate { + text: qsTr("Proform 2000 (not pro)") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.proform_2000_treadmill + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: {settings.proform_2000_treadmill = checked; window.settings_restart_to_apply = true; } + } + SwitchDelegate { + text: qsTr("Proform 8.5") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.proform_8_5_treadmill + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: {settings.proform_8_5_treadmill = checked; window.settings_restart_to_apply = true; } + } SwitchDelegate { text: qsTr("Proform Pro 1000") spacing: 0 @@ -5410,7 +5717,21 @@ import QtQuick.Dialogs 1.0 Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillWidth: true onClicked: {settings.proform_pro_1000_treadmill = checked; window.settings_restart_to_apply = true; } - } + } + SwitchDelegate { + text: qsTr("Nordictrack L6.0S") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.proform_treadmill_l6_0s + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.proform_treadmill_l6_0s = checked; window.settings_restart_to_apply = true; } + } + SwitchDelegate { id: nordictrackT65SDelegate text: qsTr("Nordictrack T6.5S v81") @@ -5454,7 +5775,20 @@ import QtQuick.Dialogs 1.0 Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillWidth: true onClicked: { settings.nordictrack_t70_treadmill = checked; window.settings_restart_to_apply = true; } - } + } + SwitchDelegate { + text: qsTr("Nordictrack S20") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.nordictrack_s20_treadmill + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.nordictrack_s20_treadmill = checked; window.settings_restart_to_apply = true; } + } SwitchDelegate { id: nordictrackS30Delegate text: qsTr("Nordictrack S30") @@ -5484,7 +5818,7 @@ import QtQuick.Dialogs 1.0 onClicked: { settings.proform_treadmill_1800i = checked; window.settings_restart_to_apply = true; } } SwitchDelegate { - text: qsTr("Proform z1300i") + text: qsTr("Proform/NordicTrack z1300i") spacing: 0 bottomPadding: 0 topPadding: 0 @@ -5753,7 +6087,7 @@ import QtQuick.Dialogs 1.0 checked: settings.kingsmith_encrypt_v2 Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillWidth: true - onClicked: { settings.kingsmith_encrypt_v2 = checked; settings.kingsmith_encrypt_v3 = false; settings.kingsmith_encrypt_v4 = false; settings.kingsmith_encrypt_v5 = false; window.settings_restart_to_apply = true; } + onClicked: { settings.kingsmith_encrypt_v2 = checked; settings.kingsmith_encrypt_g1_walking_pad = false; settings.kingsmith_encrypt_v3 = false; settings.kingsmith_encrypt_v4 = false; settings.kingsmith_encrypt_v5 = false; window.settings_restart_to_apply = true; } } SwitchDelegate { @@ -5768,7 +6102,7 @@ import QtQuick.Dialogs 1.0 checked: settings.kingsmith_encrypt_v3 Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillWidth: true - onClicked: { settings.kingsmith_encrypt_v3 = checked; settings.kingsmith_encrypt_v2 = false; settings.kingsmith_encrypt_v4 = false; settings.kingsmith_encrypt_v5 = false; window.settings_restart_to_apply = true; } + onClicked: { settings.kingsmith_encrypt_v3 = checked; settings.kingsmith_encrypt_g1_walking_pad = false; settings.kingsmith_encrypt_v2 = false; settings.kingsmith_encrypt_v4 = false; settings.kingsmith_encrypt_v5 = false; window.settings_restart_to_apply = true; } } SwitchDelegate { @@ -5783,7 +6117,7 @@ import QtQuick.Dialogs 1.0 checked: settings.kingsmith_encrypt_v4 Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillWidth: true - onClicked: { settings.kingsmith_encrypt_v4 = checked; settings.kingsmith_encrypt_v3 = false; settings.kingsmith_encrypt_v2 = false; settings.kingsmith_encrypt_v5 = false; window.settings_restart_to_apply = true; } + onClicked: { settings.kingsmith_encrypt_v4 = checked; settings.kingsmith_encrypt_g1_walking_pad = false; settings.kingsmith_encrypt_v3 = false; settings.kingsmith_encrypt_v2 = false; settings.kingsmith_encrypt_v5 = false; window.settings_restart_to_apply = true; } } SwitchDelegate { @@ -5797,8 +6131,22 @@ import QtQuick.Dialogs 1.0 checked: settings.kingsmith_encrypt_v5 Layout.alignment: Qt.AlignLeft | Qt.AlignTop Layout.fillWidth: true - onClicked: { settings.kingsmith_encrypt_v5 = checked; settings.kingsmith_encrypt_v3 = false; settings.kingsmith_encrypt_v2 = false; settings.kingsmith_encrypt_v4 = false; window.settings_restart_to_apply = true; } + onClicked: { settings.kingsmith_encrypt_v5 = checked; settings.kingsmith_encrypt_g1_walking_pad = false; settings.kingsmith_encrypt_v3 = false; settings.kingsmith_encrypt_v2 = false; settings.kingsmith_encrypt_v4 = false; window.settings_restart_to_apply = true; } } + + SwitchDelegate { + text: qsTr("WalkingPad G1") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.kingsmith_encrypt_g1_walking_pad + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.kingsmith_encrypt_g1_walking_pad = checked; settings.kingsmith_encrypt_v5 = false; settings.kingsmith_encrypt_v3 = false; settings.kingsmith_encrypt_v2 = false; settings.kingsmith_encrypt_v4 = false; window.settings_restart_to_apply = true; } + } } } @@ -6625,6 +6973,19 @@ import QtQuick.Dialogs 1.0 Layout.fillWidth: true onClicked: { settings.hertz_xr_770 = checked; window.settings_restart_to_apply = true; } } + SwitchDelegate { + text: qsTr("iConsole Elliptical") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.iconsole_elliptical + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.iconsole_elliptical = checked; window.settings_restart_to_apply = true; } + } } } @@ -7044,7 +7405,7 @@ import QtQuick.Dialogs 1.0 horizontalAlignment: Text.AlignRight Layout.fillHeight: false Layout.alignment: Qt.AlignRight | Qt.AlignVCenter - inputMethodHints: Qt.ImhDigitsOnly + //inputMethodHints: Qt.ImhDigitsOnly onAccepted: settings.speed_offset = text onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length } @@ -7525,6 +7886,42 @@ import QtQuick.Dialogs 1.0 Layout.fillWidth: true color: Material.color(Material.Lime) } + + RowLayout { + spacing: 10 + Label { + text: qsTr("AutoLap on Distance:") + Layout.fillWidth: true + } + TextField { + id: autoLapOnDistanceTextField + text: (settings.miles_unit?settings.autolap_distance * 0.621371:settings.autolap_distance).toFixed(1) + horizontalAlignment: Text.AlignRight + Layout.fillHeight: false + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + //inputMethodHints: Qt.ImhDigitsOnly + onAccepted: settings.autolap_distance = text + onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length + } + Button { + text: "OK" + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onClicked: { settings.autolap_distance = (settings.miles_unit?autoLapOnDistanceTextField.text * 1.60934:autoLapOnDistanceTextField.text); toast.show("Setting saved!"); } + } + } + + Label { + text: qsTr("You can trigger auto laps in the FIT file based on distance. Unit: "+ (settings.miles_unit?"Mi":"KM") +" Default: 0 (disabled).") + font.bold: true + font.italic: true + font.pixelSize: 9 + textFormat: Text.PlainText + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + color: Material.color(Material.Lime) + } } } @@ -8492,6 +8889,99 @@ import QtQuick.Dialogs 1.0 } } } + + AccordionElement { + title: qsTr("Elite Aria Options") + indicatRectColor: Material.color(Material.Grey) + textColor: Material.color(Material.Yellow) + color: Material.backgroundColor + + accordionContent: ColumnLayout { + spacing: 0 + SwitchDelegate { + text: qsTr("Enable") + spacing: 0 + bottomPadding: 0 + topPadding: 0 + rightPadding: 0 + leftPadding: 0 + clip: false + checked: settings.fitmetria_fanfit_enable + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillWidth: true + onClicked: { settings.fitmetria_fanfit_enable = checked; window.settings_restart_to_apply = true; } + } + + RowLayout { + spacing: 10 + Label { + text: qsTr("Mode:") + Layout.fillWidth: true + } + ComboBox { + id: eliteAriaModeTextField + model: [ "Heart", "Power", "Manual" ] + displayText: settings.fitmetria_fanfit_mode + Layout.fillHeight: false + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onActivated: { + console.log("combomodel activated" + eliteAriaModeTextField.currentIndex) + displayText = eliteAriaModeTextField.currentValue + } + + } + Button { + text: "OK" + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onClicked: { settings.fitmetria_fanfit_mode = eliteAriaModeTextField.displayText; toast.show("Setting saved!"); } + } + } + RowLayout { + spacing: 10 + Label { + text: qsTr("Min. value (0-100):") + Layout.fillWidth: true + } + TextField { + id: eliteAriaMinTextField + text: settings.fitmetria_fanfit_min + horizontalAlignment: Text.AlignRight + Layout.fillHeight: false + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + inputMethodHints: Qt.ImhDigitsOnly + onAccepted: settings.fitmetria_fanfit_min = text + onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length + } + Button { + text: "OK" + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onClicked: { settings.fitmetria_fanfit_min = eliteAriaMinTextField.text; toast.show("Setting saved!"); } + } + } + RowLayout { + spacing: 10 + Label { + text: qsTr("Max value (0-100):") + Layout.fillWidth: true + } + TextField { + id: eliteAriaMaxTextField + text: settings.fitmetria_fanfit_max + horizontalAlignment: Text.AlignRight + Layout.fillHeight: false + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + inputMethodHints: Qt.ImhDigitsOnly + onAccepted: settings.fitmetria_fanfit_max = text + onActiveFocusChanged: if(this.focus) this.cursorPosition = this.text.length + } + Button { + text: "OK" + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + onClicked: { settings.fitmetria_fanfit_max = eliteAriaMaxTextField.text; toast.show("Setting saved!"); } + } + } + } + } } } diff --git a/src/shuaa5treadmill.cpp b/src/shuaa5treadmill.cpp index bd7665ac5..fd2a4d4f8 100644 --- a/src/shuaa5treadmill.cpp +++ b/src/shuaa5treadmill.cpp @@ -309,7 +309,7 @@ void shuaa5treadmill::characteristicChanged(const QLowEnergyCharacteristic &char if (Flags.heartRate) { if (index < newValue.length()) { - heart = ((double)((newValue.at(index)))); + heart = ((double)(((uint8_t)newValue.at(index)))); emit debug(QStringLiteral("Current Heart: ") + QString::number(heart)); } else { emit debug(QStringLiteral("Error on parsing heart!")); diff --git a/src/smartrowrower.cpp b/src/smartrowrower.cpp index 301ae87ca..7a26378f1 100644 --- a/src/smartrowrower.cpp +++ b/src/smartrowrower.cpp @@ -184,6 +184,7 @@ double smartrowrower::bikeResistanceToPeloton(double resistance) { } void smartrowrower::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -257,10 +258,10 @@ void smartrowrower::characteristicChanged(const QLowEnergyCharacteristic &charac settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 // Distance += ((Speed.value() / 3600000.0) * - // ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())) ); + // ((double)lastRefreshCharacteristicChanged.msecsTo(now)) ); Distance = distance; if (Cadence.value() > 0) { @@ -268,7 +269,7 @@ void smartrowrower::characteristicChanged(const QLowEnergyCharacteristic &charac LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) diff --git a/src/snodebike.cpp b/src/snodebike.cpp index 43d88dbca..e9ce28d68 100644 --- a/src/snodebike.cpp +++ b/src/snodebike.cpp @@ -113,6 +113,7 @@ void snodebike::serviceDiscovered(const QBluetoothUuid &gatt) { } void snodebike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); double heart = 0.0; // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); @@ -164,7 +165,7 @@ void snodebike::characteristicChanged(const QLowEnergyCharacteristic &characteri } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } index += 2; emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); @@ -208,7 +209,7 @@ void snodebike::characteristicChanged(const QLowEnergyCharacteristic &characteri // else { Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); } emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); @@ -257,7 +258,7 @@ void snodebike::characteristicChanged(const QLowEnergyCharacteristic &characteri settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 } @@ -270,7 +271,7 @@ void snodebike::characteristicChanged(const QLowEnergyCharacteristic &characteri #endif { if (Flags.heartRate) { - heart = ((double)((newValue.at(index)))); + heart = ((double)(((uint8_t)newValue.at(index)))); // index += 1; // NOTE: clang-analyzer-deadcode.DeadStores emit debug(QStringLiteral("Current Heart: ") + QString::number(heart)); } @@ -310,7 +311,7 @@ void snodebike::characteristicChanged(const QLowEnergyCharacteristic &characteri Resistance = m_pelotonResistance; emit resistanceRead(Resistance.value()); - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) { if (heart == 0.0) { diff --git a/src/solebike.cpp b/src/solebike.cpp index f42eb06eb..2d8cdb11c 100644 --- a/src/solebike.cpp +++ b/src/solebike.cpp @@ -220,6 +220,7 @@ double solebike::bikeResistanceToPeloton(double resistance) { } void solebike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -260,7 +261,7 @@ void solebike::characteristicChanged(const QLowEnergyCharacteristic &characteris } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } m_watt = GetWattFromPacket(newValue); @@ -271,17 +272,17 @@ void solebike::characteristicChanged(const QLowEnergyCharacteristic &characteris settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (Cadence.value() > 0) { CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) { diff --git a/src/soleelliptical.cpp b/src/soleelliptical.cpp index 23f6866e7..fa3121330 100644 --- a/src/soleelliptical.cpp +++ b/src/soleelliptical.cpp @@ -299,6 +299,7 @@ void soleelliptical::serviceDiscovered(const QBluetoothUuid &gatt) { } void soleelliptical::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); @@ -376,11 +377,11 @@ void soleelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara } Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; emit debug(QStringLiteral("Current speed: ") + QString::number(speed)); emit debug(QStringLiteral("Current cadence: ") + QString::number(Cadence.value())); diff --git a/src/solef80treadmill.cpp b/src/solef80treadmill.cpp index 5fef62871..07e8517ca 100644 --- a/src/solef80treadmill.cpp +++ b/src/solef80treadmill.cpp @@ -674,7 +674,7 @@ void solef80treadmill::characteristicChanged(const QLowEnergyCharacteristic &cha if (Flags.heartRate) { if (index < newValue.length()) { - heart = ((double)((newValue.at(index)))); + heart = ((double)(((uint8_t)newValue.at(index)))); emit debug(QStringLiteral("Current Heart: ") + QString::number(heart)); } else { emit debug(QStringLiteral("Error on parsing heart!")); diff --git a/src/sportsplusbike.cpp b/src/sportsplusbike.cpp index c8a8c6497..d80d0556b 100644 --- a/src/sportsplusbike.cpp +++ b/src/sportsplusbike.cpp @@ -120,6 +120,7 @@ void sportsplusbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void sportsplusbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -142,7 +143,7 @@ void sportsplusbike::characteristicChanged(const QLowEnergyCharacteristic &chara if (newValue.at(1) == 0x20) { double speed = GetSpeedFromPacket(newValue); if (!firstCharChanged) { - Distance += ((speed / 3600.0) / (1000.0 / (lastTimeCharChanged.msecsTo(QDateTime::currentDateTime())))); + Distance += ((speed / 3600.0) / (1000.0 / (lastTimeCharChanged.msecsTo(now)))); } emit debug(QStringLiteral("Current speed: ") + QString::number(speed)); @@ -151,9 +152,9 @@ void sportsplusbike::characteristicChanged(const QLowEnergyCharacteristic &chara } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } - lastTimeCharChanged = QDateTime::currentDateTime(); + lastTimeCharChanged = now; } else if (newValue.at(1) == 0x30) { double watt = GetWattFromPacket(newValue); emit debug(QStringLiteral("Current watt: ") + QString::number(watt)); @@ -193,22 +194,22 @@ void sportsplusbike::characteristicChanged(const QLowEnergyCharacteristic &chara } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } emit debug(QStringLiteral("Current speed: ") + QString::number(Speed.value())); if (!firstCharChanged) { Distance += - ((Speed.value() / 3600.0) / (1000.0 / (lastTimeCharChanged.msecsTo(QDateTime::currentDateTime())))); + ((Speed.value() / 3600.0) / (1000.0 / (lastTimeCharChanged.msecsTo(now)))); } - lastTimeCharChanged = QDateTime::currentDateTime(); + lastTimeCharChanged = now; kcal += ((((0.048 * ((double)watts()) + 1.19) * settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 } else { if (settings.value(QZSettings::power_sensor_name, QZSettings::default_power_sensor_name) @@ -224,7 +225,7 @@ void sportsplusbike::characteristicChanged(const QLowEnergyCharacteristic &chara double speed = GetSpeedFromPacket(newValue); cadence = speed * 2.685185; if (!firstCharChanged) { - Distance += ((speed / 3600.0) / (1000.0 / (lastTimeCharChanged.msecsTo(QDateTime::currentDateTime())))); + Distance += ((speed / 3600.0) / (1000.0 / (lastTimeCharChanged.msecsTo(now)))); } emit debug(QStringLiteral("Current speed: ") + QString::number(speed)); @@ -233,13 +234,13 @@ void sportsplusbike::characteristicChanged(const QLowEnergyCharacteristic &chara } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } - lastTimeCharChanged = QDateTime::currentDateTime(); + lastTimeCharChanged = now; kcal = GetKcalFromPacket(newValue); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) diff --git a/src/sportstechbike.cpp b/src/sportstechbike.cpp index 330d7beb2..67ab78714 100644 --- a/src/sportstechbike.cpp +++ b/src/sportstechbike.cpp @@ -116,6 +116,7 @@ void sportstechbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void sportstechbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -171,7 +172,7 @@ void sportstechbike::characteristicChanged(const QLowEnergyCharacteristic &chara } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } Resistance = requestResistance; emit resistanceRead(Resistance.value()); diff --git a/src/stagesbike.cpp b/src/stagesbike.cpp index c6a187d94..5a2e2bfe1 100644 --- a/src/stagesbike.cpp +++ b/src/stagesbike.cpp @@ -164,6 +164,7 @@ uint16_t stagesbike::wattsFromResistance(double resistance) { } void stagesbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -262,8 +263,8 @@ void stagesbike::characteristicChanged(const QLowEnergyCharacteristic &character if (cadence >= 0) { Cadence = cadence; } - lastGoodCadence = QDateTime::currentDateTime(); - } else if (lastGoodCadence.msecsTo(QDateTime::currentDateTime()) > 2000) { + lastGoodCadence = now; + } else if (lastGoodCadence.msecsTo(now) > 2000) { Cadence = 0; } } @@ -282,12 +283,12 @@ void stagesbike::characteristicChanged(const QLowEnergyCharacteristic &character } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value())); Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); // if we change this, also change the wattsFromResistance function. We can create a standard function in @@ -339,7 +340,7 @@ void stagesbike::characteristicChanged(const QLowEnergyCharacteristic &character settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight + now)))); //(( (0.048* Output in watts +1.19) * body weight // in kg * 3.5) / 200 ) / 60 emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); } @@ -357,7 +358,7 @@ void stagesbike::characteristicChanged(const QLowEnergyCharacteristic &character } } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; if (!noVirtualDevice) { #ifdef Q_OS_IOS diff --git a/src/strydrunpowersensor.cpp b/src/strydrunpowersensor.cpp index 9e03eb660..e5cb87a2e 100644 --- a/src/strydrunpowersensor.cpp +++ b/src/strydrunpowersensor.cpp @@ -78,7 +78,7 @@ void strydrunpowersensor::update() { // gattWriteCharacteristic.isValid() && // gattNotify1Characteristic.isValid() && /*initDone*/) { - update_metrics(true, watts()); + update_metrics(false, watts()); if (requestInclination != -100) { Inclination = treadmillInclinationOverrideReverse(requestInclination); @@ -119,7 +119,9 @@ void strydrunpowersensor::characteristicChanged(const QLowEnergyCharacteristic & if (newValue.length() > 3) { powerReceived = true; - m_watt = (((uint16_t)((uint8_t)newValue.at(3)) << 8) | (uint16_t)((uint8_t)newValue.at(2))); + double weight = settings.value(QZSettings::weight, QZSettings::default_weight).toFloat(); + double vwatts = ((9.8 * weight) * (currentInclination().value() / 100.0)); + m_watt = (((uint16_t)((uint8_t)newValue.at(3)) << 8) | (uint16_t)((uint8_t)newValue.at(2))) + vwatts; } emit powerChanged(m_watt.value()); @@ -286,7 +288,7 @@ void strydrunpowersensor::characteristicChanged(const QLowEnergyCharacteristic & if (Flags.heartRate) { if (index < newValue.length()) { - double heart = ((double)((newValue.at(index)))); + double heart = ((double)(((uint8_t)newValue.at(index)))); emit debug(QStringLiteral("Current Heart: ") + QString::number(heart)); } else { emit debug(QStringLiteral("Error on parsing heart!")); @@ -422,6 +424,15 @@ void strydrunpowersensor::characteristicChanged(const QLowEnergyCharacteristic & qDebug() << QStringLiteral("Current GroundContactMS:") << GroundContactMS.value(); qDebug() << QStringLiteral("Current VerticalOscillationMM:") << VerticalOscillationMM.value(); } + } else if (characteristic.uuid() == QBluetoothUuid(QStringLiteral("7e78aa19-72cd-d3b8-a81f-5b7e589bea0f"))) { + if (newValue.length() == 20 && newValue.at(0) == 0x32) { + GroundContactMS = (((uint16_t)((uint8_t)newValue.at(5)) << 8) | (uint16_t)((uint8_t)newValue.at(4))); + emit groundContactChanged(GroundContactMS.value()); + //VerticalOscillationMM = (((uint16_t)((uint8_t)newValue.at(4)) << 8) | (uint16_t)((uint8_t)newValue.at(3))); + //emit verticalOscillationChanged(VerticalOscillationMM.value()); + qDebug() << QStringLiteral("Current GroundContactMS:") << GroundContactMS.value(); + qDebug() << QStringLiteral("Current VerticalOscillationMM:") << VerticalOscillationMM.value(); + } } if (!noVirtualDevice) { diff --git a/src/tacxneo2.cpp b/src/tacxneo2.cpp index 9baa336c6..350823e6f 100644 --- a/src/tacxneo2.cpp +++ b/src/tacxneo2.cpp @@ -175,6 +175,7 @@ void tacxneo2::serviceDiscovered(const QBluetoothUuid &gatt) { } void tacxneo2::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -236,8 +237,8 @@ void tacxneo2::characteristicChanged(const QLowEnergyCharacteristic &characteris if (cadence >= 0 && cadence < 255) { Cadence = cadence; } - lastGoodCadence = QDateTime::currentDateTime(); - } else if (lastGoodCadence.msecsTo(QDateTime::currentDateTime()) > 2000) { + lastGoodCadence = now; + } else if (lastGoodCadence.msecsTo(now) > 2000) { Cadence = 0; } @@ -249,7 +250,7 @@ void tacxneo2::characteristicChanged(const QLowEnergyCharacteristic &characteris .toDouble(); Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); // Resistance = ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | // (uint16_t)((uint8_t)newValue.at(index)))); debug("Current Resistance: " + @@ -284,9 +285,9 @@ void tacxneo2::characteristicChanged(const QLowEnergyCharacteristic &characteris settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; emit debug(QStringLiteral("Current CrankRevsRead: ") + QString::number(CrankRevsRead)); emit debug(QStringLiteral("Last CrankEventTime: ") + QString::number(LastCrankEventTime)); diff --git a/src/technogymmyruntreadmill.cpp b/src/technogymmyruntreadmill.cpp index c3523cbb3..6d5caa88b 100644 --- a/src/technogymmyruntreadmill.cpp +++ b/src/technogymmyruntreadmill.cpp @@ -395,7 +395,7 @@ void technogymmyruntreadmill::characteristicChanged(const QLowEnergyCharacterist if (Flags.heartRate) { if (index < newValue.length()) { - heart = ((double)((newValue.at(index)))); + heart = ((double)(((uint8_t)newValue.at(index)))); emit debug(QStringLiteral("Current Heart: ") + QString::number(heart)); } else { emit debug(QStringLiteral("Error on parsing heart!")); diff --git a/src/technogymmyruntreadmillrfcomm.cpp b/src/technogymmyruntreadmillrfcomm.cpp index 0ef1a4f3f..6017e49de 100644 --- a/src/technogymmyruntreadmillrfcomm.cpp +++ b/src/technogymmyruntreadmillrfcomm.cpp @@ -38,8 +38,8 @@ void technogymmyruntreadmillrfcomm::deviceDiscovered(const QBluetoothDeviceInfo // the full discovery works but it requires 2 or more minutes to complete. // if you have issue finding your device, open the Technogym app, connect to your // treadmill, and then you should be safe to use QZ for that moment on - discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); - //discoveryAgent->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery); + //discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); + discoveryAgent->start(QBluetoothServiceDiscoveryAgent::MinimalDiscovery); return; } } @@ -61,7 +61,12 @@ void technogymmyruntreadmillrfcomm::serviceFinished(void) { #endif emit debug(QStringLiteral("Create socket")); - socket->connectToService(serialPortService); + if(!found) { + qDebug() << QStringLiteral("technogymmyruntreadmillrfcomm::serviceFinished, no service found, trying workaround"); + socket->connectToService(bluetoothDevice.address(), QBluetoothUuid(QBluetoothUuid::SerialPort)); + } else { + socket->connectToService(serialPortService); + } emit debug(QStringLiteral("ConnectToService done")); } } diff --git a/src/templateinfosenderbuilder.cpp b/src/templateinfosenderbuilder.cpp index 6707472f1..083d098a9 100644 --- a/src/templateinfosenderbuilder.cpp +++ b/src/templateinfosenderbuilder.cpp @@ -995,13 +995,13 @@ void TemplateInfoSenderBuilder::buildContext(bool forceReinit) { obj.setProperty(QStringLiteral("moving_h"), el.hour()); obj.setProperty(QStringLiteral("speed"), (dep = device->currentSpeed()).value()); obj.setProperty(QStringLiteral("speed_avg"), dep.average()); - obj.setProperty(QStringLiteral("speed_color"), dep.color()); + obj.setProperty(QStringLiteral("speed_color"), homeform::singleton()->speed->valueFontColor()); obj.setProperty(QStringLiteral("speed_lapavg"), dep.lapAverage()); obj.setProperty(QStringLiteral("speed_lapmax"), dep.lapMax()); obj.setProperty(QStringLiteral("calories"), device->calories().value()); obj.setProperty(QStringLiteral("distance"), device->odometer()); obj.setProperty(QStringLiteral("heart"), (dep = device->currentHeart()).value()); - obj.setProperty(QStringLiteral("heart_color"), dep.color()); + obj.setProperty(QStringLiteral("heart_color"), homeform::singleton()->heart->valueFontColor()); obj.setProperty(QStringLiteral("heart_avg"), dep.average()); obj.setProperty(QStringLiteral("heart_lapavg"), dep.lapAverage()); obj.setProperty(QStringLiteral("heart_max"), dep.max()); @@ -1011,7 +1011,7 @@ void TemplateInfoSenderBuilder::buildContext(bool forceReinit) { obj.setProperty(QStringLiteral("difficult"), device->difficult()); obj.setProperty(QStringLiteral("watts"), (dep = device->wattsMetric()).value()); obj.setProperty(QStringLiteral("watts_avg"), dep.average()); - obj.setProperty(QStringLiteral("watts_color"), dep.color()); + obj.setProperty(QStringLiteral("watts_color"), homeform::singleton()->watt->valueFontColor()); obj.setProperty(QStringLiteral("watts_lapavg"), dep.lapAverage()); obj.setProperty(QStringLiteral("watts_max"), dep.max()); obj.setProperty(QStringLiteral("watts_lapmax"), dep.lapMax()); @@ -1037,6 +1037,16 @@ void TemplateInfoSenderBuilder::buildContext(bool forceReinit) { obj.setProperty(QStringLiteral("row_remaining_time_m"), 0); obj.setProperty(QStringLiteral("row_remaining_time_h"), 0); } + if (homeform::singleton()->trainingProgram()) { + el = homeform::singleton()->trainingProgram()->remainingTime(); + obj.setProperty(QStringLiteral("remaining_time_s"), el.second()); + obj.setProperty(QStringLiteral("remaining_time_m"), el.minute()); + obj.setProperty(QStringLiteral("remaining_time_h"), el.hour()); + } else { + obj.setProperty(QStringLiteral("remaining_time_s"), 0); + obj.setProperty(QStringLiteral("remaining_time_m"), 0); + obj.setProperty(QStringLiteral("remaining_time_h"), 0); + } obj.setProperty( QStringLiteral("nickName"), (nickName = settings.value(QZSettings::user_nickname, QZSettings::default_user_nickname).toString()) @@ -1054,16 +1064,17 @@ void TemplateInfoSenderBuilder::buildContext(bool forceReinit) { obj.setProperty(QStringLiteral("power_zone_lapavg"), ((bike *)device)->currentPowerZone().lapAverage()); obj.setProperty(QStringLiteral("power_zone_lapmax"), ((bike *)device)->currentPowerZone().lapMax()); obj.setProperty(QStringLiteral("target_power_zone"), ((bike *)device)->targetPowerZone().value()); + obj.setProperty(QStringLiteral("power_zone_color"), homeform::singleton()->ftp->valueFontColor()); obj.setProperty(QStringLiteral("peloton_resistance"), (dep = ((bike *)device)->pelotonResistance()).value()); obj.setProperty(QStringLiteral("peloton_resistance_avg"), dep.average()); - obj.setProperty(QStringLiteral("peloton_resistance_color"), dep.color()); + obj.setProperty(QStringLiteral("peloton_resistance_color"), homeform::singleton()->peloton_resistance->valueFontColor()); obj.setProperty(QStringLiteral("peloton_resistance_lapavg"), dep.lapAverage()); obj.setProperty(QStringLiteral("peloton_resistance_lapmax"), dep.lapMax()); obj.setProperty(QStringLiteral("peloton_req_resistance"), (dep = ((bike *)device)->lastRequestedPelotonResistance()).value()); obj.setProperty(QStringLiteral("cadence"), (dep = ((bike *)device)->currentCadence()).value()); - obj.setProperty(QStringLiteral("cadence_color"), dep.color()); + obj.setProperty(QStringLiteral("cadence_color"), homeform::singleton()->cadence->valueFontColor()); obj.setProperty(QStringLiteral("cadence_avg"), dep.average()); obj.setProperty(QStringLiteral("cadence_lapavg"), dep.lapAverage()); obj.setProperty(QStringLiteral("cadence_lapmax"), dep.lapMax()); @@ -1086,7 +1097,7 @@ void TemplateInfoSenderBuilder::buildContext(bool forceReinit) { (dep = ((rower *)device)->pelotonResistance()).value()); obj.setProperty(QStringLiteral("peloton_resistance_avg"), dep.average()); obj.setProperty(QStringLiteral("cadence"), (dep = ((rower *)device)->currentCadence()).value()); - obj.setProperty(QStringLiteral("cadence_color"), dep.color()); + obj.setProperty(QStringLiteral("cadence_color"), homeform::singleton()->cadence->valueFontColor()); obj.setProperty(QStringLiteral("cadence_avg"), dep.average()); obj.setProperty(QStringLiteral("cadence_lapavg"), dep.lapAverage()); obj.setProperty(QStringLiteral("cadence_lapmax"), dep.lapMax()); @@ -1106,7 +1117,7 @@ void TemplateInfoSenderBuilder::buildContext(bool forceReinit) { obj.setProperty(QStringLiteral("target_inclination"), ((treadmill *)device)->lastRequestedInclination().value()); obj.setProperty(QStringLiteral("cadence"), (dep = ((treadmill *)device)->currentCadence()).value()); - obj.setProperty(QStringLiteral("cadence_color"), dep.color()); + obj.setProperty(QStringLiteral("cadence_color"), homeform::singleton()->cadence->valueFontColor()); obj.setProperty(QStringLiteral("cadence_avg"), dep.average()); obj.setProperty(QStringLiteral("cadence_lapavg"), dep.lapAverage()); obj.setProperty(QStringLiteral("cadence_lapmax"), dep.lapMax()); @@ -1122,7 +1133,7 @@ void TemplateInfoSenderBuilder::buildContext(bool forceReinit) { (dep = ((treadmill *)device)->currentVerticalOscillation()).value()); } else if (tp == bluetoothdevice::ELLIPTICAL) { obj.setProperty(QStringLiteral("cadence"), (dep = ((elliptical *)device)->currentCadence()).value()); - obj.setProperty(QStringLiteral("cadence_color"), dep.color()); + obj.setProperty(QStringLiteral("cadence_color"), homeform::singleton()->cadence->valueFontColor()); obj.setProperty(QStringLiteral("cadence_avg"), dep.average()); obj.setProperty(QStringLiteral("cadence_lapavg"), dep.lapAverage()); obj.setProperty(QStringLiteral("cadence_lapmax"), dep.lapMax()); diff --git a/src/toorxtreadmill.cpp b/src/toorxtreadmill.cpp index a73b687f7..6f11f8b6d 100644 --- a/src/toorxtreadmill.cpp +++ b/src/toorxtreadmill.cpp @@ -20,7 +20,8 @@ toorxtreadmill::toorxtreadmill() { void toorxtreadmill::deviceDiscovered(const QBluetoothDeviceInfo &device) { emit debug(QStringLiteral("Found new device: ") + device.name() + QStringLiteral(" (") + device.address().toString() + ')'); - if (device.name().startsWith(QStringLiteral("TRX ROUTE KEY"))) { + if (device.name().startsWith(QStringLiteral("TRX ROUTE KEY")) || + device.name().toUpper().startsWith(QStringLiteral("BH-TR-"))) { bluetoothDevice = device; // Create a discovery agent and connect to its signals diff --git a/src/trainprogram.cpp b/src/trainprogram.cpp index 71d9202b6..788e1f897 100644 --- a/src/trainprogram.cpp +++ b/src/trainprogram.cpp @@ -29,6 +29,12 @@ trainprogram::trainprogram(const QList &rows, bluetooth *b, QString *d this->description = *description; if (tags) this->tags = *tags; + + if(settings.value(QZSettings::zwift_username, QZSettings::default_zwift_username).toString().length() > 0) { + zwift_auth_token = new AuthToken(settings.value(QZSettings::zwift_username, QZSettings::default_zwift_username).toString(), settings.value(QZSettings::zwift_password, QZSettings::default_zwift_password).toString()); + zwift_auth_token->getAccessToken(); + } + /* int c = 0; for (c = 0; c < rows.length(); c++) { @@ -436,27 +442,27 @@ double trainprogram::avgInclinationNext100Meters(int step) { if (sum == 1) { return rows.at(currentStep).inclination; } - return avg / (double)sum; + return avg / (double)km; } if (c == currentStep) km += (rows.at(c).distance - currentStepDistance); else km += (rows.at(c).distance); - avg += rows.at(c).inclination; + avg += rows.at(c).inclination * rows.at(c).distance; sum++; } else { if (sum == 1) { return rows.at(currentStep).inclination; } - return avg / (double)sum; + return avg / (double)km; } c++; } if (sum == 1) { return rows.at(currentStep).inclination; } - return avg / (double)sum; + return avg / (double)km; } double trainprogram::avgAzimuthNext300Meters() { @@ -572,7 +578,6 @@ void trainprogram::scheduler() { QMutexLocker(&this->schedulerMutex); QSettings settings; - // outside the if case about a valid train program because the information for the floating window url should be // sent anyway if (settings.value(QZSettings::peloton_companion_workout_ocr, QZSettings::default_companion_peloton_workout_ocr) @@ -590,6 +595,91 @@ void trainprogram::scheduler() { (bluetoothManager->device()->currentSpeed().value() <= 0 && !settings.value(QZSettings::continuous_moving, QZSettings::default_continuous_moving).toBool()) || bluetoothManager->device()->isPaused()) { + + if(bluetoothManager->device() && bluetoothManager->device()->deviceType() == bluetoothdevice::TREADMILL && + settings.value(QZSettings::zwift_username, QZSettings::default_zwift_username).toString().length() > 0 && + zwift_auth_token->access_token.length() > 0) { + if(!zwift_world) { + zwift_world = new World(1, zwift_auth_token->getAccessToken()); + qDebug() << "creating zwift api world"; + } + else { +#ifdef Q_OS_IOS +#ifndef IO_UNDER_QT + if(!h) + h = new lockscreen(); +#endif +#endif + if(zwift_player_id == -1) { + QString id = zwift_world->player_id(); + QJsonParseError parseError; + QJsonDocument document = QJsonDocument::fromJson(id.toLocal8Bit(), &parseError); + QJsonObject ride = document.object(); + qDebug() << "zwift api player" << ride; + zwift_player_id = ride[QStringLiteral("id")].toInt(); + } else { + static int zwift_counter = 5; + if(zwift_counter++ >= 4) { + zwift_counter = 0; + QByteArray bb = zwift_world->playerStatus(zwift_player_id); +#ifdef Q_OS_IOS +#ifndef IO_UNDER_QT + h->zwift_api_decodemessage_player(bb.data(), bb.length()); + float alt = h->zwift_api_getaltitude(); + float distance = h->zwift_api_getdistance(); +#else + float alt = 0; + float distance = 0; +#endif +#elif defined(Q_OS_ANDROID) + QAndroidJniEnvironment env; + jbyteArray d = env->NewByteArray(bb.length()); + jbyte *b = env->GetByteArrayElements(d, 0); + for (int i = 0; i < bb.length(); i++) + b[i] = bb[i]; + env->SetByteArrayRegion(d, 0, bb.length(), b); + + QAndroidJniObject::callStaticMethod( + "org/cagnulen/qdomyoszwift/ZwiftAPI", "zwift_api_decodemessage_player", "([B)V", d); + env->DeleteLocalRef(d); + + float alt = QAndroidJniObject::callStaticMethod("org/cagnulen/qdomyoszwift/ZwiftAPI", "getAltitude", "()F"); + float distance = QAndroidJniObject::callStaticMethod("org/cagnulen/qdomyoszwift/ZwiftAPI", "getDistance", "()F"); +#else + float alt = 0; + float distance = 0; +#endif + static float old_distance = 0; + static float old_alt = 0; + + qDebug() << "zwift api incline1" << old_distance << old_alt << distance << alt; + + if(old_distance > 0) { + float delta = distance - old_distance; + float deltaA = alt - old_alt; + float incline = (deltaA / delta) / 2.0; + if(delta > 1) { + bool zwift_negative_inclination_x2 = + settings.value(QZSettings::zwift_negative_inclination_x2, QZSettings::default_zwift_negative_inclination_x2) + .toBool(); + double offset = + settings.value(QZSettings::zwift_inclination_offset, QZSettings::default_zwift_inclination_offset).toDouble(); + double gain = + settings.value(QZSettings::zwift_inclination_gain, QZSettings::default_zwift_inclination_gain).toDouble(); + double grade = (incline * gain) + offset; + if (zwift_negative_inclination_x2 && incline < 0) { + grade = ((incline * 2.0) * gain) + offset; + } + qDebug() << "zwift api incline" << incline << grade << delta << deltaA; + bluetoothManager->device()->changeInclination(grade, grade); + } + } + old_distance = distance; + old_alt = alt; + } + } + } + } // in case no workout has been selected // Zwift OCR @@ -764,7 +854,8 @@ void trainprogram::scheduler() { emit changeRequestedPelotonResistance(rows.at(0).requested_peloton_resistance); } - if (rows.at(0).inclination != -200 && bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE) { + if (rows.at(0).inclination != -200 && (bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE || + (bluetoothManager->device()->deviceType() == bluetoothdevice::ELLIPTICAL && !((elliptical*)bluetoothManager->device())->inclinationAvailableByHardware()))) { // this should be converted in a signal as all the other signals... double bikeResistanceOffset = settings.value(QZSettings::bike_resistance_offset, QZSettings::default_bike_resistance_offset) @@ -776,7 +867,7 @@ void trainprogram::scheduler() { double inc = rows.at(0).inclination; bluetoothManager->device()->changeResistance((resistance_t)(round(inc * bikeResistanceGain)) + bikeResistanceOffset + 1); // resistance start from 1) - if (!((bike *)bluetoothManager->device())->inclinationAvailableByHardware()) + if (bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE && !((bike *)bluetoothManager->device())->inclinationAvailableByHardware()) bluetoothManager->device()->setInclination(inc); qDebug() << QStringLiteral("trainprogram change inclination") + QString::number(inc); emit changeInclination(inc, inc); @@ -916,7 +1007,8 @@ void trainprogram::scheduler() { } if (rows.at(currentStep).inclination != -200 && - bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE) { + (bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE || + (bluetoothManager->device()->deviceType() == bluetoothdevice::ELLIPTICAL && !((elliptical*)bluetoothManager->device())->inclinationAvailableByHardware()))) { // this should be converted in a signal as all the other signals... double bikeResistanceOffset = settings @@ -931,7 +1023,7 @@ void trainprogram::scheduler() { bluetoothManager->device()->changeResistance((resistance_t)(round(inc * bikeResistanceGain)) + bikeResistanceOffset + 1); // resistance start from 1) - if (!((bike *)bluetoothManager->device())->inclinationAvailableByHardware()) + if (bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE && !((bike *)bluetoothManager->device())->inclinationAvailableByHardware()) bluetoothManager->device()->setInclination(inc); qDebug() << QStringLiteral("trainprogram change inclination") + QString::number(inc); emit changeInclination(inc, inc); @@ -1201,8 +1293,8 @@ bool trainprogram::saveXML(const QString &filename, const QList &rows) void trainprogram::save(const QString &filename) { saveXML(filename, rows); } -trainprogram *trainprogram::load(const QString &filename, bluetooth *b) { - if (!filename.right(3).toUpper().compare(QStringLiteral("ZWO"))) { +trainprogram *trainprogram::load(const QString &filename, bluetooth *b, QString Extension) { + if (!Extension.toUpper().compare(QStringLiteral("ZWO"))) { QString description = ""; QString tags = ""; diff --git a/src/trainprogram.h b/src/trainprogram.h index a6d1a4410..7aa07e9f8 100644 --- a/src/trainprogram.h +++ b/src/trainprogram.h @@ -8,6 +8,13 @@ #include #include +#ifdef Q_OS_IOS +#include "ios/lockscreen.h" +#endif + +#include "zwift-api/PlayerStateWrapper.h" +#include "zwift-api/zwift_client_auth.h" + class trainrow { public: QTime duration = QTime(0, 0, 0, 0); @@ -62,7 +69,7 @@ class trainprogram : public QObject { trainprogram(const QList &, bluetooth *b, QString *description = nullptr, QString *tags = nullptr, bool videoAvailable = false); void save(const QString &filename); - static trainprogram *load(const QString &filename, bluetooth *b); + static trainprogram *load(const QString &filename, bluetooth *b, QString Extension); static QList loadXML(const QString &filename); static bool saveXML(const QString &filename, const QList &rows); QTime totalElapsedTime(); @@ -155,6 +162,15 @@ private slots: QUdpSocket* pelotonOCRsocket = nullptr; void pelotonOCRcomputeTime(QString t); + + AuthToken* zwift_auth_token = nullptr; + World* zwift_world = nullptr; + int zwift_player_id = -1; + +#ifdef Q_OS_IOS + lockscreen *h = 0; +#endif + }; #endif // TRAINPROGRAM_H diff --git a/src/treadmill.cpp b/src/treadmill.cpp index ab30f8a36..fac76d1f3 100644 --- a/src/treadmill.cpp +++ b/src/treadmill.cpp @@ -17,6 +17,18 @@ void treadmill::changeSpeed(double speed) { requestSpeed = (speed * m_difficult) + m_difficult_offset; } void treadmill::changeInclination(double grade, double inclination) { + QSettings settings; + double treadmill_incline_min = settings.value(QZSettings::treadmill_incline_min, QZSettings::default_treadmill_incline_min).toDouble(); + double treadmill_incline_max = settings.value(QZSettings::treadmill_incline_max, QZSettings::default_treadmill_incline_max).toDouble(); + + if(grade < treadmill_incline_min) { + grade = treadmill_incline_min; + qDebug() << "grade override due to treadmill_incline_min" << grade; + } else if(grade > treadmill_incline_max) { + grade = treadmill_incline_max; + qDebug() << "grade override due to treadmill_incline_max" << grade; + } + m_lastRawInclinationRequested = grade; Q_UNUSED(inclination); qDebug() << "changeInclination" << grade << autoResistanceEnable << m_inclination_difficult @@ -119,6 +131,7 @@ void treadmill::clearStats() { Speed.clear(false); KCal.clear(true); Distance.clear(true); + Distance1s.clear(true); Heart.clear(false); m_jouls.clear(true); elevationAcc = 0; @@ -138,6 +151,7 @@ void treadmill::setPaused(bool p) { Speed.setPaused(p); KCal.setPaused(p); Distance.setPaused(p); + Distance1s.setPaused(p); Heart.setPaused(p); m_jouls.setPaused(p); m_watt.setPaused(p); @@ -154,6 +168,7 @@ void treadmill::setLap() { Speed.setLap(false); KCal.setLap(true); Distance.setLap(true); + Distance1s.setLap(true); Heart.setLap(false); m_jouls.setLap(true); m_watt.setLap(false); diff --git a/src/truetreadmill.cpp b/src/truetreadmill.cpp index edc6fc829..6ceb6a078 100644 --- a/src/truetreadmill.cpp +++ b/src/truetreadmill.cpp @@ -139,6 +139,7 @@ void truetreadmill::serviceDiscovered(const QBluetoothUuid &gatt) { } void truetreadmill::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); QSettings settings; QString heartRateBeltName = @@ -214,11 +215,11 @@ void truetreadmill::characteristicChanged(const QLowEnergyCharacteristic &charac settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastTimeCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 Distance += ((speed / (double)3600.0) / - ((double)1000.0 / (double)(lastTimeCharacteristicChanged.msecsTo(QDateTime::currentDateTime())))); - lastTimeCharacteristicChanged = QDateTime::currentDateTime(); + ((double)1000.0 / (double)(lastTimeCharacteristicChanged.msecsTo(now)))); + lastTimeCharacteristicChanged = now; } emit debug(QStringLiteral("Current speed: ") + QString::number(speed)); diff --git a/src/trxappgateusbbike.cpp b/src/trxappgateusbbike.cpp index ce0bcec40..61a02399d 100644 --- a/src/trxappgateusbbike.cpp +++ b/src/trxappgateusbbike.cpp @@ -984,7 +984,8 @@ void trxappgateusbbike::deviceDiscovered(const QBluetoothDeviceInfo &device) { bike_type = TYPE::DKN_MOTION; qDebug() << QStringLiteral("DKN MOTION bike found"); - } else if (device.name().toUpper().startsWith(QStringLiteral("FITHIWAY"))) { + } else if (device.name().toUpper().startsWith(QStringLiteral("FITHIWAY")) || + device.name().toUpper().startsWith(QStringLiteral("FIT HI WAY"))) { bike_type = TYPE::FITHIWAY; qDebug() << QStringLiteral("FITHIWAY bike found"); } diff --git a/src/ultrasportbike.cpp b/src/ultrasportbike.cpp index b2d3f0ee2..9e922a729 100644 --- a/src/ultrasportbike.cpp +++ b/src/ultrasportbike.cpp @@ -159,6 +159,7 @@ double ultrasportbike::bikeResistanceToPeloton(double resistance) { } void ultrasportbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -189,7 +190,7 @@ void ultrasportbike::characteristicChanged(const QLowEnergyCharacteristic &chara { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } if (watts()) @@ -198,17 +199,17 @@ void ultrasportbike::characteristicChanged(const QLowEnergyCharacteristic &chara settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (Cadence.value() > 0) { CrankRevs++; LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) { diff --git a/src/virtualbike.cpp b/src/virtualbike.cpp index 4088e9b63..b4bd57d4b 100644 --- a/src/virtualbike.cpp +++ b/src/virtualbike.cpp @@ -28,6 +28,7 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear bool echelon = settings.value(QZSettings::virtual_device_echelon, QZSettings::default_virtual_device_echelon).toBool(); bool ifit = settings.value(QZSettings::virtual_device_ifit, QZSettings::default_virtual_device_ifit).toBool(); + bool garmin_bluetooth_compatibility = settings.value(QZSettings::garmin_bluetooth_compatibility, QZSettings::default_garmin_bluetooth_compatibility).toBool(); if (settings.value(QZSettings::dircon_yes, QZSettings::default_dircon_yes).toBool()) { dirconManager = new DirconManager(Bike, bikeResistanceOffset, bikeResistanceGain, this); @@ -53,12 +54,12 @@ virtualbike::virtualbike(bluetoothdevice *t, bool noWriteResistance, bool noHear #ifndef IO_UNDER_QT bool ios_peloton_workaround = settings.value(QZSettings::ios_peloton_workaround, QZSettings::default_ios_peloton_workaround).toBool(); - if (ios_peloton_workaround && !cadence && !echelon && !ifit && !heart_only && !power) { + if ((ios_peloton_workaround && !cadence && !echelon && !ifit && !heart_only) || garmin_bluetooth_compatibility) { qDebug() << "ios_zwift_workaround activated!"; h = new lockscreen(); h->virtualbike_zwift_ios( - settings.value(QZSettings::bike_heartrate_service, QZSettings::default_bike_heartrate_service).toBool()); + settings.value(QZSettings::bike_heartrate_service, QZSettings::default_bike_heartrate_service).toBool(), garmin_bluetooth_compatibility); } else #endif diff --git a/src/virtualtreadmill.cpp b/src/virtualtreadmill.cpp index b9c4de675..919c954e4 100644 --- a/src/virtualtreadmill.cpp +++ b/src/virtualtreadmill.cpp @@ -353,7 +353,7 @@ void virtualtreadmill::treadmillProvider() { if (h->virtualtreadmill_updateFTMS( normalizeSpeed, 0, (uint16_t)((treadmill *)treadMill)->currentCadence().value() * cadence_multiplier, (uint16_t)((treadmill *)treadMill)->wattsMetric().value(), - treadMill->currentInclination().value() * 10)) { + treadMill->currentInclination().value() * 10, (uint64_t)(((treadmill *)treadMill)->odometer() * 1000.0))) { h->virtualtreadmill_setHeartRate(((treadmill *)treadMill)->currentHeart().value()); lastSlopeChanged = h->virtualtreadmill_lastChangeCurrentSlope(); if ((uint64_t)QDateTime::currentSecsSinceEpoch() < lastSlopeChanged + slopeTimeoutSecs) diff --git a/src/windows/zwift-incline-ai-server.py b/src/windows/zwift-incline-ai-server.py new file mode 100644 index 000000000..8aad322da --- /dev/null +++ b/src/windows/zwift-incline-ai-server.py @@ -0,0 +1,117 @@ +# iFit-Wolf3 - Autoincline control of treadmill via ADB and OCR +# Author: Al Udell + +# Revised: November 25, 2023 + +# zwift-incline.py - take Zwift screenshot, crop incline, OCR incline + +# imports +import cv2 +import numpy as np +import re +from PIL import Image, ImageGrab +import requests +import win32gui + +# Enable DPI aware on Windows +from ctypes import windll +user32 = windll.user32 +user32.SetProcessDPIAware() + +# Take Zwift screenshot - windowed mode only +hwnd = win32gui.FindWindow(None, 'Zwift') +if not hwnd: + print("Zwift is not running") + exit() +x, y, x1, y1 = win32gui.GetClientRect(hwnd) +x, y = win32gui.ClientToScreen(hwnd, (x, y)) +x1, y1 = win32gui.ClientToScreen(hwnd, (x1, y1)) +screenshot = ImageGrab.grab((x, y, x1, y1)) + +# Scale image to 3000 x 2000 +screenshot = screenshot.resize((3000, 2000)) + +# Crop image to incline area +screenwidth, screenheight = screenshot.size + +# Values for Zwift regular incline +col1 = int(screenwidth/3000 * 2800) +row1 = int(screenheight/2000 * 90) +col2 = int(screenwidth/3000 * 2975) +row2 = int(screenheight/2000 * 195) + +cropped = screenshot.crop((col1, row1, col2, row2)) + +# Convert image to np array +cropped_np = np.array(cropped) + +# Convert np array to PIL +cropped_pil = Image.fromarray(cropped_np) + +# Convert PIL image to cv2 RGB +cropped_cv2 = cv2.cvtColor(np.array(cropped_pil), cv2.COLOR_RGB2BGR) + +# Convert cv2 RGB to HSV +result = cropped_cv2.copy() +image = cv2.cvtColor(cropped_cv2, cv2.COLOR_BGR2HSV) + +# Isolate white mask +lower = np.array([0,0,159]) +upper = np.array([0,0,255]) +mask0 = cv2.inRange(image, lower, upper) +result0 = cv2.bitwise_and(result, result, mask=mask0) + +# Isolate yellow mask +lower = np.array([24,239,241]) +upper = np.array([24,253,255]) +mask1 = cv2.inRange(image, lower, upper) +result1 = cv2.bitwise_and(result, result, mask=mask1) + +# Isolate orange mask +lower = np.array([8,191,243]) +upper = np.array([8,192,243]) +mask2 = cv2.inRange(image, lower, upper) +result2 = cv2.bitwise_and(result, result, mask=mask2) + +# Isolate red mask +lower = np.array([0,255,255]) +upper = np.array([10,255,255]) +mask3 = cv2.inRange(image, lower, upper) +result3 = cv2.bitwise_and(result, result, mask=mask3) + +# Join colour masks +mask = mask0+mask1+mask2+mask3 + +# Set output image to zero everywhere except mask +merge = image.copy() +merge[np.where(mask==0)] = 0 + +# Convert to grayscale +gray = cv2.cvtColor(merge, cv2.COLOR_BGR2GRAY) + +# Convert to black/white by threshold +ret,bin = cv2.threshold(gray, 70, 255, cv2.THRESH_BINARY_INV) + +# Apply gaussian blur +gaussianBlur = cv2.GaussianBlur(bin,(3,3),0) + +# Write zwift image +cv2.imwrite('zwift.png', gaussianBlur, [cv2.IMWRITE_PNG_COMPRESSION, 0]) + +# OCR image +image_data = open("zwift.png","rb").read() +ocr = requests.post("http://localhost:32168/v1/image/ocr", files={"image":image_data}).json() + +# Extract label values from the 'predictions' list and merge into a single string +labels = [prediction['label'] for prediction in ocr.get('predictions', [])] +result = ''.join(labels) + +# Remove all characters that are not "-" and integers from OCR text +pattern = r"[^-\d]+" +ocr_text = re.sub(pattern, "", result) +if ocr_text: + incline = ocr_text +else: + incline = 'None' + +print(incline) diff --git a/src/windows/zwift-incline-climb-portal-ai-server.py b/src/windows/zwift-incline-climb-portal-ai-server.py new file mode 100644 index 000000000..1809faba1 --- /dev/null +++ b/src/windows/zwift-incline-climb-portal-ai-server.py @@ -0,0 +1,118 @@ +# iFit-Wolf3 - Autoincline control of treadmill via ADB and OCR +# Author: Al Udell +# Revised: November 25, 2023 + +# zwift-incline-climb-portal.py - take Zwift screenshot, crop incline, OCR incline + +# imports +import cv2 +import numpy as np +import re + +from PIL import Image, ImageGrab +import requests +import win32gui +#import time + +# Enable DPI aware on Windows +from ctypes import windll +user32 = windll.user32 +user32.SetProcessDPIAware() + +# Take Zwift screenshot - windowed mode only +hwnd = win32gui.FindWindow(None, 'Zwift') +if not hwnd: + print("Zwift is not running") + exit() +x, y, x1, y1 = win32gui.GetClientRect(hwnd) +x, y = win32gui.ClientToScreen(hwnd, (x, y)) +x1, y1 = win32gui.ClientToScreen(hwnd, (x1, y1)) +screenshot = ImageGrab.grab((x, y, x1, y1)) + +# Scale image to 3000 x 2000 +screenshot = screenshot.resize((3000, 2000)) + +# 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 = screenshot.crop((col1, row1, col2, row2)) + +# Convert image to np array +cropped_np = np.array(cropped) + +# Convert np array to PIL +cropped_pil = Image.fromarray(cropped_np) + +# Convert PIL image to cv2 RGB +cropped_cv2 = cv2.cvtColor(np.array(cropped_pil), cv2.COLOR_RGB2BGR) + +# Convert cv2 RGB to HSV +result = cropped_cv2.copy() +image = cv2.cvtColor(cropped_cv2, cv2.COLOR_BGR2HSV) + +# Isolate white mask +lower = np.array([0,0,159]) +upper = np.array([0,0,255]) +mask0 = cv2.inRange(image, lower, upper) +result0 = cv2.bitwise_and(result, result, mask=mask0) + +# Isolate yellow mask +lower = np.array([24,239,241]) +upper = np.array([24,253,255]) +mask1 = cv2.inRange(image, lower, upper) +result1 = cv2.bitwise_and(result, result, mask=mask1) + +# Isolate orange mask +lower = np.array([8,191,243]) +upper = np.array([8,192,243]) +mask2 = cv2.inRange(image, lower, upper) +result2 = cv2.bitwise_and(result, result, mask=mask2) + +# Isolate red mask +lower = np.array([0,255,255]) +upper = np.array([10,255,255]) +mask3 = cv2.inRange(image, lower, upper) +result3 = cv2.bitwise_and(result, result, mask=mask3) + +# Join colour masks +mask = mask0+mask1+mask2+mask3 + +# Set output image to zero everywhere except mask +merge = image.copy() +merge[np.where(mask==0)] = 0 + +# Convert to grayscale +gray = cv2.cvtColor(merge, cv2.COLOR_BGR2GRAY) + +# Convert to black/white by threshold +ret,bin = cv2.threshold(gray, 70, 255, cv2.THRESH_BINARY_INV) + +# Apply gaussian blur +gaussianBlur = cv2.GaussianBlur(bin,(3,3),0) + +# Write zwift image +cv2.imwrite('zwift.png', gaussianBlur, [cv2.IMWRITE_PNG_COMPRESSION, 0]) + +# OCR image +image_data = open("zwift.png","rb").read() +ocr = requests.post("http://localhost:32168/v1/image/ocr", files={"image":image_data}).json() + +# Extract label values from the 'predictions' list and merge into a single string +labels = [prediction['label'] for prediction in ocr.get('predictions', [])] +result = ''.join(labels) + +# Remove all characters that are not "-" and integers from OCR text +pattern = r"[^-\d]+" +ocr_text = re.sub(pattern, "", result) +if ocr_text: + incline = ocr_text +else: + incline = 'None' + +print(incline) diff --git a/src/windows/zwift-incline-climb-portal.py b/src/windows/zwift-incline-climb-portal.py index b605b6a82..267473402 100644 --- a/src/windows/zwift-incline-climb-portal.py +++ b/src/windows/zwift-incline-climb-portal.py @@ -1,107 +1,116 @@ -# iFit-Wolf3 - Autoincline control of treadmill via ADB and OCR -# Author: Al Udell -# Revised: August 16, 2023 - -# zwift-incline-climb-portal.py - take Zwift screenshot, crop incline, OCR incline - -# imports -import cv2 -import numpy as np -import re -from datetime import datetime -from paddleocr import PaddleOCR -from PIL import Image, ImageGrab - -# Take Zwift screenshot -screenshot = ImageGrab.grab() - -# Scale image to 3000 x 2000 -screenshot = screenshot.resize((3000, 2000)) - -# 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 = screenshot.crop((col1, row1, col2, row2)) - -# Scale image to correct size for borderless window mode -width, height = cropped.size -cropped = cropped.resize((int(width * 1.3), int(height * 1.3))) - -# Convert image to np array -cropped_np = np.array(cropped) - -# Convert np array to PIL -cropped_pil = Image.fromarray(cropped_np) - -# Convert PIL image to cv2 RGB -cropped_cv2 = cv2.cvtColor(np.array(cropped_pil), cv2.COLOR_RGB2BGR) - -# Convert cv2 RGB to HSV -result = cropped_cv2.copy() -image = cv2.cvtColor(cropped_cv2, cv2.COLOR_BGR2HSV) - -# Isolate white mask -lower = np.array([0,0,159]) -upper = np.array([0,0,255]) -mask0 = cv2.inRange(image, lower, upper) -result0 = cv2.bitwise_and(result, result, mask=mask0) - -# Isolate yellow mask -lower = np.array([24,239,241]) -upper = np.array([24,253,255]) -mask1 = cv2.inRange(image, lower, upper) -result1 = cv2.bitwise_and(result, result, mask=mask1) - -# Isolate orange mask -lower = np.array([8,191,243]) -upper = np.array([8,192,243]) -mask2 = cv2.inRange(image, lower, upper) -result2 = cv2.bitwise_and(result, result, mask=mask2) - -# Isolate red mask -lower = np.array([0,255,255]) -upper = np.array([10,255,255]) -mask3 = cv2.inRange(image, lower, upper) -result3 = cv2.bitwise_and(result, result, mask=mask3) - -# Join colour masks -mask = mask0+mask1+mask2+mask3 - -# Set output image to zero everywhere except mask -merge = image.copy() -merge[np.where(mask==0)] = 0 - -# Convert to grayscale -gray = cv2.cvtColor(merge, cv2.COLOR_BGR2GRAY) - -# Convert to black/white by threshold -ret,bin = cv2.threshold(gray, 70, 255, cv2.THRESH_BINARY_INV) - -# Apply gaussian blur -gaussianBlur = cv2.GaussianBlur(bin,(3,3),0) - -# OCR image -ocr = PaddleOCR(lang='en', use_gpu=False, enable_mkldnn=True, use_angle_cls=False, table=False, layout=False, show_log=False) -result = ocr.ocr(gaussianBlur, cls=False, det=True, rec=True) - -# Extract OCR text -ocr_text = '' -for line in result: - for word in line: - ocr_text += f"{word[1][0]}" - -# Remove all characters that are not "-" and integers from OCR text -pattern = r"[^-\d]+" -ocr_text = re.sub(pattern, "", ocr_text) -if ocr_text: - incline = ocr_text -else: - incline = 'None' - -print(incline) +# iFit-Wolf3 - Autoincline control of treadmill via ADB and OCR +# Author: Al Udell +# Revised: November 23, 2023 + +# zwift-incline-climb-portal.py - take Zwift screenshot, crop incline, OCR incline + +# imports +import cv2 +import numpy as np +import re +import win32gui +from datetime import datetime +from paddleocr import PaddleOCR +from PIL import Image, ImageGrab + +# Enable DPI aware on Windows +from ctypes import windll +user32 = windll.user32 +user32.SetProcessDPIAware() + +# Take Zwift screenshot - windowed mode only +hwnd = win32gui.FindWindow(None, 'Zwift') +if not hwnd: + print("Zwift is not running") + exit() +x, y, x1, y1 = win32gui.GetClientRect(hwnd) +x, y = win32gui.ClientToScreen(hwnd, (x, y)) +x1, y1 = win32gui.ClientToScreen(hwnd, (x1, y1)) +screenshot = ImageGrab.grab((x, y, x1, y1)) + +# Scale image to 3000 x 2000 +screenshot = screenshot.resize((3000, 2000)) + +# 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 = screenshot.crop((col1, row1, col2, row2)) + +# Convert image to np array +cropped_np = np.array(cropped) + +# Convert np array to PIL +cropped_pil = Image.fromarray(cropped_np) + +# Convert PIL image to cv2 RGB +cropped_cv2 = cv2.cvtColor(np.array(cropped_pil), cv2.COLOR_RGB2BGR) + +# Convert cv2 RGB to HSV +result = cropped_cv2.copy() +image = cv2.cvtColor(cropped_cv2, cv2.COLOR_BGR2HSV) + +# Isolate white mask +lower = np.array([0,0,159]) +upper = np.array([0,0,255]) +mask0 = cv2.inRange(image, lower, upper) +result0 = cv2.bitwise_and(result, result, mask=mask0) + +# Isolate yellow mask +lower = np.array([24,239,241]) +upper = np.array([24,253,255]) +mask1 = cv2.inRange(image, lower, upper) +result1 = cv2.bitwise_and(result, result, mask=mask1) + +# Isolate orange mask +lower = np.array([8,191,243]) +upper = np.array([8,192,243]) +mask2 = cv2.inRange(image, lower, upper) +result2 = cv2.bitwise_and(result, result, mask=mask2) + +# Isolate red mask +lower = np.array([0,255,255]) +upper = np.array([10,255,255]) +mask3 = cv2.inRange(image, lower, upper) +result3 = cv2.bitwise_and(result, result, mask=mask3) + +# Join colour masks +mask = mask0+mask1+mask2+mask3 + +# Set output image to zero everywhere except mask +merge = image.copy() +merge[np.where(mask==0)] = 0 + +# Convert to grayscale +gray = cv2.cvtColor(merge, cv2.COLOR_BGR2GRAY) + +# Convert to black/white by threshold +ret,bin = cv2.threshold(gray, 70, 255, cv2.THRESH_BINARY_INV) + +# Apply gaussian blur +gaussianBlur = cv2.GaussianBlur(bin,(3,3),0) + +# OCR image +ocr = PaddleOCR(lang='en', use_gpu=False, show_log=False, det_db_unclip_ratio=2.0, det_db_box_thresh=0.40, drop_score=0.40, rec_algorithm='CRNN', cls_model_dir='paddleocr/ch_ppocr_mobile_v2.0_cls_infer', det_model_dir='paddleocr/en_PP-OCRv3_det_infer', rec_model_dir='paddleocr/en_PP-OCRv3_rec_infer') +result = ocr.ocr(gaussianBlur, cls=False, det=True, rec=True) + +# Extract OCR text +ocr_text = '' +for line in result: + for word in line: + ocr_text += f"{word[1][0]}" + +# Remove all characters that are not "-" and integers from OCR text +pattern = r"[^-\d]+" +ocr_text = re.sub(pattern, "", ocr_text) +if ocr_text: + incline = ocr_text +else: + incline = 'None' + +print(incline) diff --git a/src/windows/zwift-incline.py b/src/windows/zwift-incline.py index 7b883fa29..1f121ca2a 100644 --- a/src/windows/zwift-incline.py +++ b/src/windows/zwift-incline.py @@ -1,103 +1,116 @@ -# iFit-Wolf3 - Autoincline control of treadmill via ADB and OCR -# Author: Al Udell -# Revised: August 16, 2023 - -# zwift-incline.py - take Zwift screenshot, crop incline, OCR incline - -# imports -import cv2 -import numpy as np -import re -from datetime import datetime -from paddleocr import PaddleOCR -from PIL import Image, ImageGrab - -# Take Zwift screenshot -screenshot = ImageGrab.grab() - -# Scale image to 3000 x 2000 -screenshot = screenshot.resize((3000, 2000)) - -# Crop image to incline area -screenwidth, screenheight = screenshot.size - -# Values for Zwift regular incline -col1 = int(screenwidth/3000 * 2800) -row1 = int(screenheight/2000 * 90) -col2 = int(screenwidth/3000 * 2975) -row2 = int(screenheight/2000 * 195) - -cropped = screenshot.crop((col1, row1, col2, row2)) - -# Convert image to np array -cropped_np = np.array(cropped) - -# Convert np array to PIL -cropped_pil = Image.fromarray(cropped_np) - -# Convert PIL image to cv2 RGB -cropped_cv2 = cv2.cvtColor(np.array(cropped_pil), cv2.COLOR_RGB2BGR) - -# Convert cv2 RGB to HSV -result = cropped_cv2.copy() -image = cv2.cvtColor(cropped_cv2, cv2.COLOR_BGR2HSV) - -# Isolate white mask -lower = np.array([0,0,159]) -upper = np.array([0,0,255]) -mask0 = cv2.inRange(image, lower, upper) -result0 = cv2.bitwise_and(result, result, mask=mask0) - -# Isolate yellow mask -lower = np.array([24,239,241]) -upper = np.array([24,253,255]) -mask1 = cv2.inRange(image, lower, upper) -result1 = cv2.bitwise_and(result, result, mask=mask1) - -# Isolate orange mask -lower = np.array([8,191,243]) -upper = np.array([8,192,243]) -mask2 = cv2.inRange(image, lower, upper) -result2 = cv2.bitwise_and(result, result, mask=mask2) - -# Isolate red mask -lower = np.array([0,255,255]) -upper = np.array([10,255,255]) -mask3 = cv2.inRange(image, lower, upper) -result3 = cv2.bitwise_and(result, result, mask=mask3) - -# Join colour masks -mask = mask0+mask1+mask2+mask3 - -# Set output image to zero everywhere except mask -merge = image.copy() -merge[np.where(mask==0)] = 0 - -# Convert to grayscale -gray = cv2.cvtColor(merge, cv2.COLOR_BGR2GRAY) - -# Convert to black/white by threshold -ret,bin = cv2.threshold(gray, 70, 255, cv2.THRESH_BINARY_INV) - -# Apply gaussian blur -gaussianBlur = cv2.GaussianBlur(bin,(3,3),0) - -# OCR image -ocr = PaddleOCR(lang='en', use_gpu=False, enable_mkldnn=True, use_angle_cls=False, table=False, layout=False, show_log=False) -result = ocr.ocr(gaussianBlur, cls=False, det=True, rec=True) - -# Extract OCR text -ocr_text = '' -for line in result: - for word in line: - ocr_text += f"{word[1][0]}" - -# Remove all characters that are not "-" and integers from OCR text -pattern = r"[^-\d]+" -ocr_text = re.sub(pattern, "", ocr_text) -if ocr_text: - incline = ocr_text -else: - incline = 'None' - -print(incline) +# iFit-Wolf3 - Autoincline control of treadmill via ADB and OCR +# Author: Al Udell +# Revised: November 23, 2023 + +# zwift-incline.py - take Zwift screenshot, crop incline, OCR incline + +# imports +import cv2 +import numpy as np +import re +import win32gui +from datetime import datetime +from paddleocr import PaddleOCR +from PIL import Image, ImageGrab + +# Enable DPI aware on Windows +from ctypes import windll +user32 = windll.user32 +user32.SetProcessDPIAware() + +# Take Zwift screenshot - windowed mode only +hwnd = win32gui.FindWindow(None, 'Zwift') +if not hwnd: + print("Zwift is not running") + exit() +x, y, x1, y1 = win32gui.GetClientRect(hwnd) +x, y = win32gui.ClientToScreen(hwnd, (x, y)) +x1, y1 = win32gui.ClientToScreen(hwnd, (x1, y1)) +screenshot = ImageGrab.grab((x, y, x1, y1)) + +# Scale image to 3000 x 2000 +screenshot = screenshot.resize((3000, 2000)) + +# Crop image to incline area +screenwidth, screenheight = screenshot.size + +# Values for Zwift regular incline +col1 = int(screenwidth/3000 * 2800) +row1 = int(screenheight/2000 * 90) +col2 = int(screenwidth/3000 * 2975) +row2 = int(screenheight/2000 * 195) + +cropped = screenshot.crop((col1, row1, col2, row2)) + +# Convert image to np array +cropped_np = np.array(cropped) + +# Convert np array to PIL +cropped_pil = Image.fromarray(cropped_np) + +# Convert PIL image to cv2 RGB +cropped_cv2 = cv2.cvtColor(np.array(cropped_pil), cv2.COLOR_RGB2BGR) + +# Convert cv2 RGB to HSV +result = cropped_cv2.copy() +image = cv2.cvtColor(cropped_cv2, cv2.COLOR_BGR2HSV) + +# Isolate white mask +lower = np.array([0,0,159]) +upper = np.array([0,0,255]) +mask0 = cv2.inRange(image, lower, upper) +result0 = cv2.bitwise_and(result, result, mask=mask0) + +# Isolate yellow mask +lower = np.array([24,239,241]) +upper = np.array([24,253,255]) +mask1 = cv2.inRange(image, lower, upper) +result1 = cv2.bitwise_and(result, result, mask=mask1) + +# Isolate orange mask +lower = np.array([8,191,243]) +upper = np.array([8,192,243]) +mask2 = cv2.inRange(image, lower, upper) +result2 = cv2.bitwise_and(result, result, mask=mask2) + +# Isolate red mask +lower = np.array([0,255,255]) +upper = np.array([10,255,255]) +mask3 = cv2.inRange(image, lower, upper) +result3 = cv2.bitwise_and(result, result, mask=mask3) + +# Join colour masks +mask = mask0+mask1+mask2+mask3 + +# Set output image to zero everywhere except mask +merge = image.copy() +merge[np.where(mask==0)] = 0 + +# Convert to grayscale +gray = cv2.cvtColor(merge, cv2.COLOR_BGR2GRAY) + +# Convert to black/white by threshold +ret,bin = cv2.threshold(gray, 70, 255, cv2.THRESH_BINARY_INV) + +# Apply gaussian blur +gaussianBlur = cv2.GaussianBlur(bin,(3,3),0) + +# OCR image +ocr = PaddleOCR(lang='en', use_gpu=False, show_log=False, det_db_unclip_ratio=2.0, det_db_box_thresh=0.40, drop_score=0.40, rec_algorithm='CRNN', cls_model_dir='paddleocr/ch_ppocr_mobile_v2.0_cls_infer', det_model_dir='paddleocr/en_PP-OCRv3_det_infer', rec_model_dir='paddleocr/en_PP-OCRv3_rec_infer') +result = ocr.ocr(gaussianBlur, cls=False, det=True, rec=True) + +# Extract OCR text +ocr_text = '' +for line in result: + for word in line: + ocr_text += f"{word[1][0]}" + +# Remove all characters that are not "-" and integers from OCR text +pattern = r"[^-\d]+" +ocr_text = re.sub(pattern, "", ocr_text) +if ocr_text: + incline = ocr_text +else: + incline = 'None' + +print(incline) diff --git a/src/windows/zwift-workout-ai-server.py b/src/windows/zwift-workout-ai-server.py new file mode 100644 index 000000000..e8c86bcb9 --- /dev/null +++ b/src/windows/zwift-workout-ai-server.py @@ -0,0 +1,74 @@ +# iFit-Workout - Auto-incline and auto-speed control of treadmill via ADB and OCR for Zwift workouts +# Author: Al Udell +# Revised: November 25, 2023 + +# zwift-workout.py - take Zwift screenshot, crop speed/incline instruction, OCR speed/incline + +# imports +import cv2 +import numpy as np +import re +from PIL import Image, ImageGrab +import requests +import win32gui + +# Enable DPI aware on Windows +from ctypes import windll +user32 = windll.user32 +user32.SetProcessDPIAware() + +# Take Zwift screenshot - windowed mode only +hwnd = win32gui.FindWindow(None, 'Zwift') +if not hwnd: + print("Zwift is not running") + exit() +x, y, x1, y1 = win32gui.GetClientRect(hwnd) +x, y = win32gui.ClientToScreen(hwnd, (x, y)) +x1, y1 = win32gui.ClientToScreen(hwnd, (x1, y1)) +screenshot = ImageGrab.grab((x, y, x1, y1)) + +# Scale image to 3000 x 2000 +screenshot = screenshot.resize((3000, 2000)) + +# Crop image to workout instruction area +screenwidth, screenheight = screenshot.size + +# Values for Zwift workout instructions +col1 = int(screenwidth/3000 * 1010) +row1 = int(screenheight/2000 * 260) +col2 = int(screenwidth/3000 * 1285) +row2 = int(screenheight/2000 * 480) + +cropped = screenshot.crop((col1, row1, col2, row2)) + +# Convert image to np array +cropped_np = np.array(cropped) + +# Write zwift image +cv2.imwrite('zwift.png', cropped_np, [cv2.IMWRITE_PNG_COMPRESSION, 0]) + +# OCR image +image_data = open("zwift.png","rb").read() +ocr = requests.post("http://localhost:32168/v1/image/ocr", files={"image":image_data}).json() + +# Extract label values from the 'predictions' list and merge into a single string +labels = [prediction['label'] for prediction in ocr.get('predictions', [])] +result = ' '.join(labels) + +# Find the speed number +if "kph" in result.lower(): + pattern = r'-?\d+(?:\.\d+)?' + numbers = re.findall(pattern, result) + speed = str(float(numbers[1])) +else: + speed = 'None' + +# Find the incline number +if "incline" in result.lower(): + pattern = r'-?\d+(?:\.\d+)?' + numbers = re.findall(pattern, result) + incline = str(float(numbers[0])) +else: + incline = 'None' + +print(speed + ";" + incline) diff --git a/src/windows/zwift-workout.py b/src/windows/zwift-workout.py index b5f2c76b8..5d822daac 100644 --- a/src/windows/zwift-workout.py +++ b/src/windows/zwift-workout.py @@ -1,71 +1,75 @@ -# iFit-Workout - Auto-incline and auto-speed control of treadmill via ADB and OCR for Zwift workouts -# Author: Al Udell -# Revised: August 16, 2023 - -# zwift-workout.py - take Zwift screenshot, crop speed/incline instruction, OCR speed/incline - -# imports -import cv2 -import numpy as np -import re -from datetime import datetime -from paddleocr import PaddleOCR -from PIL import Image, ImageGrab - -# Take Zwift screenshot -screenshot = ImageGrab.grab() - -# Scale image to 3000 x 2000 -screenshot = screenshot.resize((3000, 2000)) - -# Crop image to workout instruction area -screenwidth, screenheight = screenshot.size - -# Values for Zwift workout instructions -col1 = int(screenwidth/3000 * 1010) -row1 = int(screenheight/2000 * 260) -col2 = int(screenwidth/3000 * 1285) -row2 = int(screenheight/2000 * 480) - -cropped = screenshot.crop((col1, row1, col2, row2)) - -# Scale image to correct size for borderless window mode -width, height = cropped.size -cropped = cropped.resize((int(width * 0.99), int(height * 0.99))) - -# Convert image to np array -cropped_np = np.array(cropped) - -# OCR image -ocr = PaddleOCR(lang='en', use_gpu=False, enable_mkldnn=True, use_angle_cls=False, table=False, layout=False, show_log=False) -result = ocr.ocr(cropped_np, cls=False, det=True, rec=True) - -# Extract OCR text -ocr_text = '' -for line in result: - for word in line: - ocr_text += f"{word[1][0]} " - -# Find the speed number -num_pattern = r'\d+(\.\d+)?' # Regular expression pattern to match numbers with optional decimal places -unit_pattern = r'\s+(kph|mph)' # Regular expression pattern to match "kph" or "mph" units -speed_match = re.search(num_pattern + unit_pattern, ocr_text) -if speed_match: - speed = speed_match.group(0) - pattern = r'\d+\.\d+' - speed = re.findall(pattern, speed)[0] -else: - speed = 'None' - -# Find the incline number -incline_pattern = r'-?\d+\s*%' # Regular expression pattern to match numbers with "%" -incline_match = re.search(incline_pattern, ocr_text) -if incline_match: - incline = incline_match.group(0) - pattern = r'-?\d+' - incline = re.findall(pattern, incline)[0] -else: - incline = 'None' - -print(f"{speed};{incline}") - +# iFit-Workout - Auto-incline and auto-speed control of treadmill via ADB and OCR for Zwift workouts +# Author: Al Udell +# Revised: November 23, 2023 + +# zwift-workout.py - take Zwift screenshot, crop speed/incline instruction, OCR speed/incline + +# imports +import cv2 +import numpy as np +import re +import win32gui +from datetime import datetime +from paddleocr import PaddleOCR +from PIL import Image, ImageGrab + +# Enable DPI aware on Windows +from ctypes import windll +user32 = windll.user32 +user32.SetProcessDPIAware() + +# Take Zwift screenshot - windowed mode only +hwnd = win32gui.FindWindow(None, 'Zwift') +if not hwnd: + print("Zwift is not running") + exit() +x, y, x1, y1 = win32gui.GetClientRect(hwnd) +x, y = win32gui.ClientToScreen(hwnd, (x, y)) +x1, y1 = win32gui.ClientToScreen(hwnd, (x1, y1)) +screenshot = ImageGrab.grab((x, y, x1, y1)) + +# Scale image to 3000 x 2000 +screenshot = screenshot.resize((3000, 2000)) + +# Crop image to workout instruction area +screenwidth, screenheight = screenshot.size + +# Values for Zwift workout instructions +col1 = int(screenwidth/3000 * 1010) +row1 = int(screenheight/2000 * 260) +col2 = int(screenwidth/3000 * 1285) +row2 = int(screenheight/2000 * 480) + +cropped = screenshot.crop((col1, row1, col2, row2)) + +# Convert image to np array +cropped_np = np.array(cropped) + +# OCR image +ocr = PaddleOCR(lang='en', use_gpu=False, show_log=False, det_db_unclip_ratio=2.0, det_db_box_thresh=0.40, drop_score=0.40, rec_algorithm='CRNN', cls_model_dir='paddleocr/ch_ppocr_mobile_v2.0_cls_infer', det_model_dir='paddleocr/en_PP-OCRv3_det_infer', rec_model_dir='paddleocr/en_PP-OCRv3_rec_infer') +result = ocr.ocr(cropped_np, cls=False, det=True, rec=True) + +# Extract OCR text +ocr_text = '' +for line in result: + for word in line: + ocr_text += f"{word[1][0]} " + +# Find the speed number +if "kph" in ocr_text.lower(): + pattern = r'-?\d+(?:\.\d+)?' + numbers = re.findall(pattern, ocr_text) + speed = str(float(numbers[1])) +else: + speed = 'None' + +# Find the incline number +if "incline" in ocr_text.lower(): + pattern = r'-?\d+(?:\.\d+)?' + numbers = re.findall(pattern, ocr_text) + incline = str(float(numbers[0])) +else: + incline = 'None' + +print(speed + ";" + incline) + diff --git a/src/windows_zwift_incline_paddleocr_thread.cpp b/src/windows_zwift_incline_paddleocr_thread.cpp index 33b49338f..41e40287d 100644 --- a/src/windows_zwift_incline_paddleocr_thread.cpp +++ b/src/windows_zwift_incline_paddleocr_thread.cpp @@ -1,11 +1,15 @@ #include "windows_zwift_incline_paddleocr_thread.h" #include "elliptical.h" +#if __has_include("aiserver.h") +#include "aiserver.h" +#endif #include "treadmill.h" #include #include #include #include #include +#include #include #include #include @@ -36,9 +40,21 @@ void windows_zwift_incline_paddleocr_thread::run() { QString windows_zwift_incline_paddleocr_thread::runPython(QString command) { #ifdef Q_OS_WINDOWS + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + + QString currentPath = env.value("PATH"); + QString updatedPath = currentPath + ";" + QCoreApplication::applicationDirPath() + "\\python\\x64;C:\\Program Files\\CodeProject\\AI\\modules\\OCR\\bin\\windows\\python37\\venv\\Scripts"; + env.insert("PATH", updatedPath); + QProcess process; + process.setProcessEnvironment(env); + //qDebug() << "env >> " << env.value("PATH"); qDebug() << "run >> " << command; +#ifndef AISERVER process.start("python\\x64\\python.exe", QStringList(command.split(' '))); +#else + process.start("C:\\Program Files\\CodeProject\\AI\\modules\\OCR\\bin\\windows\\python37\\venv\\Scripts\\python.exe", QStringList(command.split(' '))); +#endif process.waitForFinished(-1); // will wait forever until finished QString out = process.readAllStandardOutput(); diff --git a/src/windows_zwift_workout_paddleocr_thread.cpp b/src/windows_zwift_workout_paddleocr_thread.cpp index a7ea7313a..29e116315 100644 --- a/src/windows_zwift_workout_paddleocr_thread.cpp +++ b/src/windows_zwift_workout_paddleocr_thread.cpp @@ -1,11 +1,15 @@ #include "windows_zwift_workout_paddleocr_thread.h" #include "elliptical.h" #include "treadmill.h" +#if __has_include("aiserver.h") +#include "aiserver.h" +#endif #include #include #include #include #include +#include #include #include #include @@ -47,9 +51,21 @@ void windows_zwift_workout_paddleocr_thread::run() { QString windows_zwift_workout_paddleocr_thread::runPython(QString command) { #ifdef Q_OS_WINDOWS + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + + QString currentPath = env.value("PATH"); + QString updatedPath = currentPath + ";" + QCoreApplication::applicationDirPath() + "\\python\\x64;C:\\Program Files\\CodeProject\\AI\\modules\\OCR\\bin\\windows\\python37\\venv\\Scripts"; + env.insert("PATH", updatedPath); + QProcess process; + process.setProcessEnvironment(env); + //qDebug() << "env >> " << env.value("PATH"); qDebug() << "run >> " << command; +#ifndef AISERVER process.start("python\\x64\\python.exe", QStringList(command.split(' '))); +#else + process.start("C:\\Program Files\\CodeProject\\AI\\modules\\OCR\\bin\\windows\\python37\\venv\\Scripts\\python.exe", QStringList(command.split(' '))); +#endif process.waitForFinished(-1); // will wait forever until finished QString out = process.readAllStandardOutput(); diff --git a/src/yesoulbike.cpp b/src/yesoulbike.cpp index 30148e974..25ccdb5ea 100644 --- a/src/yesoulbike.cpp +++ b/src/yesoulbike.cpp @@ -110,6 +110,7 @@ void yesoulbike::serviceDiscovered(const QBluetoothUuid &gatt) { } void yesoulbike::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); Q_UNUSED(characteristic); QSettings settings; @@ -139,7 +140,7 @@ void yesoulbike::characteristicChanged(const QLowEnergyCharacteristic &character } else { Speed = metric::calculateSpeedFromPower( watts(), Inclination.value(), Speed.value(), - fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); + fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit()); } if (watts()) KCal += @@ -147,10 +148,10 @@ void yesoulbike::characteristicChanged(const QLowEnergyCharacteristic &character settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastRefreshCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg + now)))); //(( (0.048* Output in watts +1.19) * body weight in kg //* 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600000.0) * - ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + ((double)lastRefreshCharacteristicChanged.msecsTo(now))); if (!settings.value(QZSettings::yesoul_peloton_formula, QZSettings::default_yesoul_peloton_formula).toBool()) { m_pelotonResistance = ((Resistance.value() * 0.88) * @@ -168,7 +169,7 @@ void yesoulbike::characteristicChanged(const QLowEnergyCharacteristic &character LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0)); } - lastRefreshCharacteristicChanged = QDateTime::currentDateTime(); + lastRefreshCharacteristicChanged = now; #ifdef Q_OS_ANDROID if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) diff --git a/src/ypooelliptical.cpp b/src/ypooelliptical.cpp index ff0c23dd8..4ac4f0c48 100644 --- a/src/ypooelliptical.cpp +++ b/src/ypooelliptical.cpp @@ -57,7 +57,12 @@ void ypooelliptical::writeCharacteristic(uint8_t *data, uint8_t data_len, const } writeBuffer = new QByteArray((const char *)data, data_len); - gattCustomService->writeCharacteristic(gattWriteCharControlPointId, *writeBuffer); + if (gattWriteCharControlPointId.properties() & QLowEnergyCharacteristic::WriteNoResponse) { + gattCustomService->writeCharacteristic(gattWriteCharControlPointId, *writeBuffer, + QLowEnergyService::WriteWithoutResponse); + } else { + gattCustomService->writeCharacteristic(gattWriteCharControlPointId, *writeBuffer); + } if (!disable_log) { emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') + QStringLiteral(" // ") + info); @@ -85,6 +90,9 @@ void ypooelliptical::update() { return; } + QSettings settings; + bool iconsole_elliptical = settings.value(QZSettings::iconsole_elliptical, QZSettings::default_iconsole_elliptical).toBool(); + if (initRequest) { initRequest = false; uint8_t init1[] = {0x02, 0x42, 0x42, 0x03}; @@ -102,13 +110,14 @@ void ypooelliptical::update() { writeCharacteristic(init5, sizeof(init5), QStringLiteral("init"), false, true); writeCharacteristic(init1, sizeof(init1), QStringLiteral("init"), false, true); writeCharacteristic(init5, sizeof(init5), QStringLiteral("init"), false, true); + initDone = true; } else if (bluetoothDevice.isValid() && m_control->state() == QLowEnergyController::DiscoveredState //&& // gattCommunicationChannelService && // gattWriteCharacteristic.isValid() && // gattNotify1Characteristic.isValid() && /*initDone*/) { - update_metrics(false, watts()); + update_metrics(iconsole_elliptical, watts()); // updating the treadmill console every second if (sec1Update++ == (500 / refresh->interval())) { @@ -170,6 +179,8 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara settings.value(QZSettings::heart_rate_belt_name, QZSettings::default_heart_rate_belt_name).toString(); bool disable_hr_frommachinery = settings.value(QZSettings::heart_ignore_builtin, QZSettings::default_heart_ignore_builtin).toBool(); + bool iconsole_elliptical = + settings.value(QZSettings::iconsole_elliptical, QZSettings::default_iconsole_elliptical).toBool(); emit debug(QStringLiteral(" << ") + newvalue.toHex(' ')); @@ -179,6 +190,9 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara return; } + if(iconsole_elliptical && initDone == false) + initRequest = true; + union flags { struct { uint32_t moreData : 1; @@ -205,7 +219,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara flags Flags; - if (characteristic.uuid() == QBluetoothUuid((quint16)0x2ACE)) { + if (characteristic.uuid() == QBluetoothUuid((quint16)0x2ACE) && !iconsole_elliptical) { if (newvalue.length() == 18) { qDebug() << QStringLiteral("let's wait for the next piece of frame"); @@ -358,7 +372,7 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara #endif { if (Flags.heartRate && !disable_hr_frommachinery && lastPacket.length() > index) { - Heart = ((double)((lastPacket.at(index)))); + Heart = ((double)(((uint8_t)lastPacket.at(index)))); // index += 1; // NOTE: clang-analyzer-deadcode.DeadStores emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); } else { @@ -377,6 +391,39 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara if (Flags.remainingTime) { // todo } + } else if (iconsole_elliptical) { + if (newvalue.length() == 15) { + Speed = (double)((((uint8_t)newvalue.at(10)) << 8) | ((uint8_t)newvalue.at(9))) / 100.0; + Cadence = newvalue.at(6); + + Distance += ((Speed.value() / 3600000.0) * + ((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))); + + if (watts()) + KCal += ((((0.048 * ((double)watts()) + 1.19) * + settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / + 200.0) / + (60000.0 / + ((double)lastRefreshCharacteristicChanged.msecsTo( + QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + // kg * 3.5) / 200 ) / 60 + +#ifdef Q_OS_ANDROID + if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) + Heart = (uint8_t)KeepAwakeHelper::heart(); + else +#endif + { + + } + + emit debug(QStringLiteral("Current speed: ") + QString::number(Speed.value())); + emit debug(QStringLiteral("Current cadence: ") + QString::number(Cadence.value())); + emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value())); + emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value())); + emit debug(QStringLiteral("Current Watt: ") + QString::number(watts())); + emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value())); + } } else { return; } @@ -388,18 +435,18 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara update_hr_from_external(); } -#ifdef Q_OS_IOS -#ifndef IO_UNDER_QT -/* - bool cadence = settings.value(QZSettings::bike_cadence_sensor, QZSettings::default_bike_cadence_sensor).toBool(); - bool ios_peloton_workaround = settings.value(QZSettings::ios_peloton_workaround, - QZSettings::default_ios_peloton_workaround).toBool(); if (ios_peloton_workaround && cadence && h && - firstStateChanged) { h->virtualTreadmill_setCadence(currentCrankRevolutions(), lastCrankEventTime()); - h->virtualTreadmill_setHeartRate((uint8_t)metrics_override_heartrate()); - } - */ -#endif -#endif + #ifdef Q_OS_IOS + #ifndef IO_UNDER_QT + /* + bool cadence = settings.value(QZSettings::bike_cadence_sensor, QZSettings::default_bike_cadence_sensor).toBool(); + bool ios_peloton_workaround = settings.value(QZSettings::ios_peloton_workaround, + QZSettings::default_ios_peloton_workaround).toBool(); if (ios_peloton_workaround && cadence && h && + firstStateChanged) { h->virtualTreadmill_setCadence(currentCrankRevolutions(), lastCrankEventTime()); + h->virtualTreadmill_setHeartRate((uint8_t)metrics_override_heartrate()); + } + */ + #endif + #endif emit debug(QStringLiteral("Current CrankRevs: ") + QString::number(CrankRevs)); emit debug(QStringLiteral("Last CrankEventTime: ") + QString::number(LastCrankEventTime)); @@ -410,6 +457,8 @@ void ypooelliptical::characteristicChanged(const QLowEnergyCharacteristic &chara } void ypooelliptical::stateChanged(QLowEnergyService::ServiceState state) { + QSettings settings; + bool iconsole_elliptical = settings.value(QZSettings::iconsole_elliptical, QZSettings::default_iconsole_elliptical).toBool(); QMetaEnum metaEnum = QMetaEnum::fromType(); emit debug(QStringLiteral("BTLE stateChanged ") + QString::fromLocal8Bit(metaEnum.valueToKey(state))); @@ -424,6 +473,12 @@ void ypooelliptical::stateChanged(QLowEnergyService::ServiceState state) { qDebug() << QStringLiteral("all services discovered!"); for (QLowEnergyService *s : qAsConst(gattCommunicationChannelService)) { + QBluetoothUuid _gattCustomService((quint16)0xFFF0); + if (s->serviceUuid() != _gattCustomService && iconsole_elliptical) { + qDebug() << "skipping service" << s->serviceUuid(); + continue; + } + if (s->state() == QLowEnergyService::ServiceDiscovered) { // establish hook into notifications connect(s, &QLowEnergyService::characteristicChanged, this, &ypooelliptical::characteristicChanged); @@ -553,10 +608,13 @@ void ypooelliptical::ftmsCharacteristicChanged(const QLowEnergyCharacteristic &c }*/ void ypooelliptical::descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue) { + QSettings settings; + bool iconsole_elliptical = settings.value(QZSettings::iconsole_elliptical, QZSettings::default_iconsole_elliptical).toBool(); emit debug(QStringLiteral("descriptorWritten ") + descriptor.name() + QStringLiteral(" ") + newValue.toHex(' ')); if (gattCustomService != nullptr) { - initRequest = true; + if(!iconsole_elliptical) + initRequest = true; emit connectedAndDiscovered(); } } diff --git a/src/ziprotreadmill.cpp b/src/ziprotreadmill.cpp index da2196c35..fa3a7f685 100644 --- a/src/ziprotreadmill.cpp +++ b/src/ziprotreadmill.cpp @@ -173,6 +173,7 @@ void ziprotreadmill::serviceDiscovered(const QBluetoothUuid &gatt) { } void ziprotreadmill::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) { + QDateTime now = QDateTime::currentDateTime(); // qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length(); QSettings settings; QString heartRateBeltName = @@ -233,11 +234,11 @@ void ziprotreadmill::characteristicChanged(const QLowEnergyCharacteristic &chara settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) / 200.0) / (60000.0 / ((double)lastTimeCharacteristicChanged.msecsTo( - QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in + now)))); //(( (0.048* Output in watts +1.19) * body weight in // kg * 3.5) / 200 ) / 60 Distance += ((Speed.value() / 3600.0) / - (1000.0 / (lastTimeCharacteristicChanged.msecsTo(QDateTime::currentDateTime())))); + (1000.0 / (lastTimeCharacteristicChanged.msecsTo(now)))); } cadenceFromAppleWatch(); @@ -249,7 +250,7 @@ void ziprotreadmill::characteristicChanged(const QLowEnergyCharacteristic &chara qDebug() << QStringLiteral("QLowEnergyController ERROR!!") << m_control->errorString(); } - lastTimeCharacteristicChanged = QDateTime::currentDateTime(); + lastTimeCharacteristicChanged = now; firstCharacteristicChanged = false; } diff --git a/src/zwift-api/PlayerStateWrapper.h b/src/zwift-api/PlayerStateWrapper.h new file mode 100644 index 000000000..06c0c93b9 --- /dev/null +++ b/src/zwift-api/PlayerStateWrapper.h @@ -0,0 +1,178 @@ +#ifndef PLAYERSTATEWRAPPER_H +#define PLAYERSTATEWRAPPER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class ZwiftRequest: public QObject { + Q_OBJECT + +public: + ZwiftRequest(const QString& getAccessToken) : getAccessToken(getAccessToken) {} + + QString json(const QString& url) { + QNetworkRequest request(QUrl(BASE_URL + url)); + request.setRawHeader("Accept", "application/json"); + request.setRawHeader("Authorization", "Bearer " + getAccessToken.toUtf8()); + + QNetworkReply* reply = manager.get(request); + QEventLoop loop; + connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); + + if (reply->error() != QNetworkReply::NoError) { + qDebug() << "Error: " << reply->errorString(); + return ""; + } + + return reply->readAll(); + } + + QByteArray protobuf(const QString& url) { + QNetworkRequest request(QUrl(BASE_URL + url)); + request.setRawHeader("Accept", "application/x-protobuf-lite"); + request.setRawHeader("Authorization", "Bearer " + getAccessToken.toUtf8()); + + QNetworkReply* reply = manager.get(request); + QEventLoop loop; + connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); + + if (reply->error() != QNetworkReply::NoError) { + qDebug() << "Error: " << reply->errorString(); + return QByteArray(); + } + + return reply->readAll(); + } + +private: + QNetworkAccessManager manager; + const QString BASE_URL = "https://us-or-rly101.zwift.com"; + const QString getAccessToken; +}; + +class World { +public: + World(int worldId, const QString& getAccessToken) : worldId(worldId), request(getAccessToken) {} + + QString getPlayers() { + return request.json("/relay/worlds/" + QString::number(worldId)); + } + + QByteArray playerStatus(int playerId) { + QByteArray buffer = request.protobuf("/relay/worlds/" + QString::number(worldId) + "/players/" + QString::number(playerId)); + return buffer; + } + + QString player_id() { + return request.json("/api/profiles/me"); + } + +private: + int worldId; + ZwiftRequest request; +}; + +class PlayerStateWrapper { +public: + + enum TURN_SIGNALS { + RIGHT = 0, + LEFT = 1, + STRAIGHT = 2 + }; + + //PlayerStateWrapper(const zwift_messages::PlayerState& playerState) : playerState(playerState) {} + + int getRideOns() { + return (playerState.at(19) >> 24) & 0xfff; + } + + bool isTurning() { + return (playerState.at(19) & 8) != 0; + } + + bool isForward() { + return (playerState.at(19) & 4) != 0; + } + + int getCourse() { + return (playerState.at(19) & 0xff0000) >> 16; + } + + int getWorld() { + return COURSE_TO_WORLD[getCourse()]; + } + + int getRoadId() { + return (playerState.at(20) & 0xff00) >> 8; + } + + int getRoadDirection() { + return (playerState.at(20) & 0xffff000000) >> 24; + } + + TURN_SIGNALS getTurnSignal() { + int signalCode = playerState.at(20) & 0x70; + if (signalCode == 0x10) { + return RIGHT; + } else if (signalCode == 0x20) { + return LEFT; + } else if (signalCode == 0x40) { + return STRAIGHT; + } else { + return STRAIGHT; + } + } + + int getPowerUp() { + return playerState.at(20) & 0xf; + } + + bool hasFeatherBoost() { + return getPowerUp() == 0; + } + + bool hasDraftBoost() { + return getPowerUp() == 1; + } + + bool hasAeroBoost() { + return getPowerUp() == 5; + } + + int getCadence() { + //return static_cast((playerState.cadenceuhz() * 60) / 1000000); + } + + std::string operator()(const std::string& item) { + try { + //return playerState.GetReflection()->GetString(playerState, playerState.GetDescriptor()->FindFieldByName(item)); + } catch (const std::exception& e) { + qDebug() << "Error: " << e.what(); + return ""; + } + } + +private: + + QMap COURSE_TO_WORLD = {{3, 1}, {4, 2}, {5, 3}, {6, 1}}; + + enum COURSES { + WATOPIA = 3, + RICHMOND = 4, + LONDON = 5 + }; + + //zwift_messages::PlayerState playerState; + QByteArray playerState; +}; + +#endif // PLAYERSTATEWRAPPER_H diff --git a/src/zwift-api/zwift_client_auth.h b/src/zwift-api/zwift_client_auth.h new file mode 100644 index 000000000..5a367bce8 --- /dev/null +++ b/src/zwift-api/zwift_client_auth.h @@ -0,0 +1,116 @@ +#ifndef ZWIFT_CLIENT_AUTH_H +#define ZWIFT_CLIENT_AUTH_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class AuthToken : public QObject { + Q_OBJECT +public: + QString username; + QString password; + QString access_token; + qint64 expires_in; + QString id_token; + qint64 not_before_policy; + QString refresh_token; + qint64 refresh_expires_in; + QString session_state; + QString token_type; + qint64 access_token_expiration; + qint64 refresh_token_expiration; + + AuthToken(const QString& username, const QString& password, QObject* parent = nullptr) + : QObject(parent), username(username), password(password) {} + + bool haveValidAccessToken() const { + return !access_token.isEmpty() && QDateTime::currentMSecsSinceEpoch() < access_token_expiration; + } + + bool haveValidRefreshToken() const { + return !refresh_token.isEmpty() && QDateTime::currentMSecsSinceEpoch() < refresh_token_expiration; + } + + Q_INVOKABLE QString getAccessToken() { + if (haveValidAccessToken()) { + return access_token; + } else { + updateTokenData(); + return access_token; + } + } + +public slots: + void updateTokenData() { + if (haveValidRefreshToken()) { + QUrl url("https://secure.zwift.com/auth/realms/zwift/tokens/access/codes"); + QUrlQuery query; + query.addQueryItem("refresh_token", refresh_token); + query.addQueryItem("grant_type", "refresh_token"); + query.addQueryItem("client_id", "Zwift_Mobile_Link"); + url.setQuery(query); + + QNetworkRequest request(url); + QNetworkReply* reply = networkManager.get(request); + connect(reply, &QNetworkReply::finished, [=]() { + handleTokenResponse(reply); + }); + } else { + QUrl url("https://secure.zwift.com/auth/realms/zwift/tokens/access/codes"); + QUrlQuery postData; + postData.addQueryItem("username", username); + postData.addQueryItem("password", password); + postData.addQueryItem("grant_type", "password"); + postData.addQueryItem("client_id", "Zwift_Mobile_Link"); + + QNetworkRequest request(url); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + QNetworkReply* reply = networkManager.post(request, postData.toString(QUrl::FullyEncoded).toUtf8()); + connect(reply, &QNetworkReply::finished, [=]() { + handleTokenResponse(reply); + }); + } + } + +private slots: + void handleTokenResponse(QNetworkReply* reply) { + if (reply->error() == QNetworkReply::NoError) { + QByteArray responseData = reply->readAll(); + QJsonDocument jsonDocument = QJsonDocument::fromJson(responseData); + QJsonObject tokenData = jsonDocument.object(); + + QDateTime now = QDateTime::currentDateTime(); + access_token = tokenData["access_token"].toString(); + expires_in = tokenData["expires_in"].toInt(); + id_token = tokenData["id_token"].toString(); + not_before_policy = tokenData["not-before-policy"].toInt(); + refresh_token = tokenData["refresh_token"].toString(); + refresh_expires_in = tokenData["refresh_expires_in"].toInt(); + session_state = tokenData["session_state"].toString(); + token_type = tokenData["token_type"].toString(); + + access_token_expiration = now.toMSecsSinceEpoch() + (expires_in - 5) * 1000; + refresh_token_expiration = now.toMSecsSinceEpoch() + (refresh_expires_in - 5) * 1000; + + qDebug() << "Access Token: " << access_token; + } else { + qDebug() << "Error fetching token: " << reply->errorString(); + } + + reply->deleteLater(); + } + +private: + QNetworkAccessManager networkManager; +}; + + +#endif // ZWIFT_CLIENT_AUTH_H diff --git a/src/zwift-api/zwift_messages.pb.cc b/src/zwift-api/zwift_messages.pb.cc new file mode 100644 index 000000000..aec318c26 --- /dev/null +++ b/src/zwift-api/zwift_messages.pb.cc @@ -0,0 +1,5489 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: zwift_messages.proto + +#include "zwift_messages.pb.h" + +#include +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/wire_format_lite.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/reflection_ops.h" +#include "google/protobuf/wire_format.h" +#include "google/protobuf/generated_message_tctable_impl.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" +PROTOBUF_PRAGMA_INIT_SEG +namespace _pb = ::google::protobuf; +namespace _pbi = ::google::protobuf::internal; +namespace _fl = ::google::protobuf::internal::field_layout; + +inline constexpr WorldAttributes::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + tag3_{::int64_t{0}}, + tag5_{::int64_t{0}}, + world_time_{::int64_t{0}}, + clock_time_{::int64_t{0}}, + world_id_{0}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR WorldAttributes::WorldAttributes(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct WorldAttributesDefaultTypeInternal { + PROTOBUF_CONSTEXPR WorldAttributesDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~WorldAttributesDefaultTypeInternal() {} + union { + WorldAttributes _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 WorldAttributesDefaultTypeInternal _WorldAttributes_default_instance_; + +inline constexpr WorldAttribute::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : world_time_{::int64_t{0}}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR WorldAttribute::WorldAttribute(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct WorldAttributeDefaultTypeInternal { + PROTOBUF_CONSTEXPR WorldAttributeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~WorldAttributeDefaultTypeInternal() {} + union { + WorldAttribute _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 WorldAttributeDefaultTypeInternal _WorldAttribute_default_instance_; + template +PROTOBUF_CONSTEXPR UnknownMessage1::UnknownMessage1(::_pbi::ConstantInitialized) {} +struct UnknownMessage1DefaultTypeInternal { + PROTOBUF_CONSTEXPR UnknownMessage1DefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~UnknownMessage1DefaultTypeInternal() {} + union { + UnknownMessage1 _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UnknownMessage1DefaultTypeInternal _UnknownMessage1_default_instance_; + template +PROTOBUF_CONSTEXPR UnknownMessage::UnknownMessage(::_pbi::ConstantInitialized) {} +struct UnknownMessageDefaultTypeInternal { + PROTOBUF_CONSTEXPR UnknownMessageDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~UnknownMessageDefaultTypeInternal() {} + union { + UnknownMessage _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UnknownMessageDefaultTypeInternal _UnknownMessage_default_instance_; + +inline constexpr SegmentResult::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : first_name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + last_name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + finish_time_str_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + id_{::int64_t{0}}, + rider_id_{::int64_t{0}}, + event_subgroup_id_{::int64_t{0}}, + elapsed_ms_{::int64_t{0}}, + powermeter_{0}, + weight_{0}, + power_{0}, + heartrate_{0}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR SegmentResult::SegmentResult(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct SegmentResultDefaultTypeInternal { + PROTOBUF_CONSTEXPR SegmentResultDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~SegmentResultDefaultTypeInternal() {} + union { + SegmentResult _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SegmentResultDefaultTypeInternal _SegmentResult_default_instance_; + +inline constexpr RiderAttributes_AttributeMessage::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : firstname_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + lastname_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + myid_{0}, + theirid_{0}, + countrycode_{0}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR RiderAttributes_AttributeMessage::RiderAttributes_AttributeMessage(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct RiderAttributes_AttributeMessageDefaultTypeInternal { + PROTOBUF_CONSTEXPR RiderAttributes_AttributeMessageDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~RiderAttributes_AttributeMessageDefaultTypeInternal() {} + union { + RiderAttributes_AttributeMessage _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 RiderAttributes_AttributeMessageDefaultTypeInternal _RiderAttributes_AttributeMessage_default_instance_; + +inline constexpr Profile::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : firstname_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + lastname_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + launchedgameclient_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + id_{0}, + male_{0}, + weight_{0}, + bodytype_{0}, + countrycode_{0}, + totaldistance_{0}, + totaldistanceclimbed_{0}, + totaltimeinminutes_{0}, + totalwatthours_{0}, + height_{0}, + totalexperiencepoints_{0}, + achievementlevel_{0}, + powersource_{0}, + age_{0}, + currentactivityid_{0}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR Profile::Profile(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct ProfileDefaultTypeInternal { + PROTOBUF_CONSTEXPR ProfileDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ProfileDefaultTypeInternal() {} + union { + Profile _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ProfileDefaultTypeInternal _Profile_default_instance_; + +inline constexpr PlayerState::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : worldtime_{::int64_t{0}}, + id_{0}, + distance_{0}, + roadtime_{0}, + laps_{0}, + speed_{0}, + roadposition_{0}, + cadenceuhz_{0}, + heartrate_{0}, + heading_{::int64_t{0}}, + power_{0}, + lean_{0}, + climbing_{0}, + time_{0}, + f19_{0}, + f20_{0}, + customisationid_{::int64_t{0}}, + progress_{0}, + justwatching_{0}, + calories_{0}, + x_{0}, + altitude_{0}, + y_{0}, + watchingriderid_{0}, + groupid_{0}, + sport_{::int64_t{0}}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR PlayerState::PlayerState(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct PlayerStateDefaultTypeInternal { + PROTOBUF_CONSTEXPR PlayerStateDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~PlayerStateDefaultTypeInternal() {} + union { + PlayerState _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 PlayerStateDefaultTypeInternal _PlayerState_default_instance_; + +inline constexpr EventSubgroupProtobuf::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : name_( + &::google::protobuf::internal::fixed_address_empty_string, + ::_pbi::ConstantInitialized()), + id_{0}, + rules_{0}, + route_{0}, + laps_{0}, + startlocation_{0}, + label_{0}, + pacetype_{0}, + jerseyhash_{0}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR EventSubgroupProtobuf::EventSubgroupProtobuf(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct EventSubgroupProtobufDefaultTypeInternal { + PROTOBUF_CONSTEXPR EventSubgroupProtobufDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~EventSubgroupProtobufDefaultTypeInternal() {} + union { + EventSubgroupProtobuf _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EventSubgroupProtobufDefaultTypeInternal _EventSubgroupProtobuf_default_instance_; + +inline constexpr ServerToClient::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : player_states_{}, + player_updates_{}, + tag1_{0}, + rider_id_{0}, + world_time_{::int64_t{0}}, + tag11_{::int64_t{0}}, + seqno_{0}, + num_msgs_{0}, + tag17_{::int64_t{0}}, + msgnum_{0}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR ServerToClient::ServerToClient(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct ServerToClientDefaultTypeInternal { + PROTOBUF_CONSTEXPR ServerToClientDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ServerToClientDefaultTypeInternal() {} + union { + ServerToClient _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ServerToClientDefaultTypeInternal _ServerToClient_default_instance_; + +inline constexpr SegmentResults::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : segment_results_{}, + world_id_{::int64_t{0}}, + segment_id_{::int64_t{0}}, + event_subgroup_id_{::int64_t{0}}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR SegmentResults::SegmentResults(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct SegmentResultsDefaultTypeInternal { + PROTOBUF_CONSTEXPR SegmentResultsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~SegmentResultsDefaultTypeInternal() {} + union { + SegmentResults _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SegmentResultsDefaultTypeInternal _SegmentResults_default_instance_; + +inline constexpr RiderAttributes::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + attributemessage_{nullptr}, + f2_{0}, + f3_{0}, + theirid_{0}, + f13_{0} {} + +template +PROTOBUF_CONSTEXPR RiderAttributes::RiderAttributes(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct RiderAttributesDefaultTypeInternal { + PROTOBUF_CONSTEXPR RiderAttributesDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~RiderAttributesDefaultTypeInternal() {} + union { + RiderAttributes _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 RiderAttributesDefaultTypeInternal _RiderAttributes_default_instance_; + +inline constexpr Profiles::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : profiles_{}, + _cached_size_{0} {} + +template +PROTOBUF_CONSTEXPR Profiles::Profiles(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct ProfilesDefaultTypeInternal { + PROTOBUF_CONSTEXPR ProfilesDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ProfilesDefaultTypeInternal() {} + union { + Profiles _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ProfilesDefaultTypeInternal _Profiles_default_instance_; + +inline constexpr ClientToServer::Impl_::Impl_( + ::_pbi::ConstantInitialized) noexcept + : _cached_size_{0}, + state_{nullptr}, + connected_{0}, + rider_id_{0}, + world_time_{::int64_t{0}}, + tag8_{::int64_t{0}}, + tag9_{::int64_t{0}}, + last_update_{::int64_t{0}}, + tag11_{::int64_t{0}}, + last_player_update_{::int64_t{0}}, + seqno_{0} {} + +template +PROTOBUF_CONSTEXPR ClientToServer::ClientToServer(::_pbi::ConstantInitialized) + : _impl_(::_pbi::ConstantInitialized()) {} +struct ClientToServerDefaultTypeInternal { + PROTOBUF_CONSTEXPR ClientToServerDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} + ~ClientToServerDefaultTypeInternal() {} + union { + ClientToServer _instance; + }; +}; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ClientToServerDefaultTypeInternal _ClientToServer_default_instance_; +static ::_pb::Metadata file_level_metadata_zwift_5fmessages_2eproto[14]; +static constexpr const ::_pb::EnumDescriptor** + file_level_enum_descriptors_zwift_5fmessages_2eproto = nullptr; +static constexpr const ::_pb::ServiceDescriptor** + file_level_service_descriptors_zwift_5fmessages_2eproto = nullptr; +const ::uint32_t TableStruct_zwift_5fmessages_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( + protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PlayerState, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.id_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.worldtime_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.distance_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.roadtime_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.laps_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.speed_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.roadposition_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.cadenceuhz_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.heartrate_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.power_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.heading_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.lean_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.climbing_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.time_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.f19_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.f20_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.progress_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.customisationid_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.justwatching_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.calories_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.x_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.altitude_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.y_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.watchingriderid_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.groupid_), + PROTOBUF_FIELD_OFFSET(::PlayerState, _impl_.sport_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.connected_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.rider_id_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.world_time_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.state_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.seqno_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.tag8_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.tag9_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.last_update_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.tag11_), + PROTOBUF_FIELD_OFFSET(::ClientToServer, _impl_.last_player_update_), + ~0u, + ~0u, + ~0u, + 0, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::SegmentResult, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.id_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.rider_id_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.event_subgroup_id_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.first_name_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.last_name_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.finish_time_str_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.elapsed_ms_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.powermeter_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.weight_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.power_), + PROTOBUF_FIELD_OFFSET(::SegmentResult, _impl_.heartrate_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::SegmentResults, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::SegmentResults, _impl_.world_id_), + PROTOBUF_FIELD_OFFSET(::SegmentResults, _impl_.segment_id_), + PROTOBUF_FIELD_OFFSET(::SegmentResults, _impl_.event_subgroup_id_), + PROTOBUF_FIELD_OFFSET(::SegmentResults, _impl_.segment_results_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::UnknownMessage1, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::UnknownMessage, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::ServerToClient, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.tag1_), + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.rider_id_), + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.world_time_), + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.seqno_), + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.player_states_), + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.player_updates_), + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.tag11_), + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.tag17_), + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.num_msgs_), + PROTOBUF_FIELD_OFFSET(::ServerToClient, _impl_.msgnum_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::WorldAttributes, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::WorldAttributes, _impl_.world_id_), + PROTOBUF_FIELD_OFFSET(::WorldAttributes, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::WorldAttributes, _impl_.tag3_), + PROTOBUF_FIELD_OFFSET(::WorldAttributes, _impl_.tag5_), + PROTOBUF_FIELD_OFFSET(::WorldAttributes, _impl_.world_time_), + PROTOBUF_FIELD_OFFSET(::WorldAttributes, _impl_.clock_time_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::WorldAttribute, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::WorldAttribute, _impl_.world_time_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _impl_.id_), + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _impl_.rules_), + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _impl_.route_), + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _impl_.laps_), + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _impl_.startlocation_), + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _impl_.label_), + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _impl_.pacetype_), + PROTOBUF_FIELD_OFFSET(::EventSubgroupProtobuf, _impl_.jerseyhash_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::RiderAttributes_AttributeMessage, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::RiderAttributes_AttributeMessage, _impl_.myid_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes_AttributeMessage, _impl_.theirid_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes_AttributeMessage, _impl_.firstname_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes_AttributeMessage, _impl_.lastname_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes_AttributeMessage, _impl_.countrycode_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::RiderAttributes, _impl_.f2_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes, _impl_.f3_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes, _impl_.attributemessage_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes, _impl_.theirid_), + PROTOBUF_FIELD_OFFSET(::RiderAttributes, _impl_.f13_), + ~0u, + ~0u, + 0, + ~0u, + ~0u, + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::Profiles, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::Profiles, _impl_.profiles_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::Profile, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.id_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.firstname_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.lastname_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.male_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.weight_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.bodytype_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.countrycode_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.totaldistance_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.totaldistanceclimbed_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.totaltimeinminutes_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.totalwatthours_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.height_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.totalexperiencepoints_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.achievementlevel_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.powersource_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.age_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.launchedgameclient_), + PROTOBUF_FIELD_OFFSET(::Profile, _impl_.currentactivityid_), +}; + +static const ::_pbi::MigrationSchema + schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + {0, -1, -1, sizeof(::PlayerState)}, + {34, 52, -1, sizeof(::ClientToServer)}, + {62, -1, -1, sizeof(::SegmentResult)}, + {81, -1, -1, sizeof(::SegmentResults)}, + {93, -1, -1, sizeof(::UnknownMessage1)}, + {101, -1, -1, sizeof(::UnknownMessage)}, + {109, -1, -1, sizeof(::ServerToClient)}, + {127, -1, -1, sizeof(::WorldAttributes)}, + {141, -1, -1, sizeof(::WorldAttribute)}, + {150, -1, -1, sizeof(::EventSubgroupProtobuf)}, + {167, -1, -1, sizeof(::RiderAttributes_AttributeMessage)}, + {180, 193, -1, sizeof(::RiderAttributes)}, + {198, -1, -1, sizeof(::Profiles)}, + {207, -1, -1, sizeof(::Profile)}, +}; + +static const ::_pb::Message* const file_default_instances[] = { + &::_PlayerState_default_instance_._instance, + &::_ClientToServer_default_instance_._instance, + &::_SegmentResult_default_instance_._instance, + &::_SegmentResults_default_instance_._instance, + &::_UnknownMessage1_default_instance_._instance, + &::_UnknownMessage_default_instance_._instance, + &::_ServerToClient_default_instance_._instance, + &::_WorldAttributes_default_instance_._instance, + &::_WorldAttribute_default_instance_._instance, + &::_EventSubgroupProtobuf_default_instance_._instance, + &::_RiderAttributes_AttributeMessage_default_instance_._instance, + &::_RiderAttributes_default_instance_._instance, + &::_Profiles_default_instance_._instance, + &::_Profile_default_instance_._instance, +}; +const char descriptor_table_protodef_zwift_5fmessages_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + "\n\024zwift_messages.proto\"\306\003\n\013PlayerState\022\n" + "\n\002id\030\001 \001(\005\022\021\n\tworldTime\030\002 \001(\003\022\020\n\010distanc" + "e\030\003 \001(\005\022\020\n\010roadTime\030\004 \001(\005\022\014\n\004laps\030\005 \001(\005\022" + "\r\n\005speed\030\006 \001(\005\022\024\n\014roadPosition\030\010 \001(\005\022\022\n\n" + "cadenceUHz\030\t \001(\005\022\021\n\theartrate\030\013 \001(\005\022\r\n\005p" + "ower\030\014 \001(\005\022\017\n\007heading\030\r \001(\003\022\014\n\004lean\030\016 \001(" + "\005\022\020\n\010climbing\030\017 \001(\005\022\014\n\004time\030\020 \001(\005\022\013\n\003f19" + "\030\023 \001(\005\022\013\n\003f20\030\024 \001(\005\022\020\n\010progress\030\025 \001(\005\022\027\n" + "\017customisationId\030\026 \001(\003\022\024\n\014justWatching\030\027" + " \001(\005\022\020\n\010calories\030\030 \001(\005\022\t\n\001x\030\031 \001(\002\022\020\n\010alt" + "itude\030\032 \001(\002\022\t\n\001y\030\033 \001(\002\022\027\n\017watchingRiderI" + "d\030\034 \001(\005\022\017\n\007groupId\030\035 \001(\005\022\r\n\005sport\030\037 \001(\003\"" + "\321\001\n\016ClientToServer\022\021\n\tconnected\030\001 \001(\005\022\020\n" + "\010rider_id\030\002 \001(\005\022\022\n\nworld_time\030\003 \001(\003\022\033\n\005s" + "tate\030\007 \001(\0132\014.PlayerState\022\r\n\005seqno\030\004 \001(\005\022" + "\014\n\004tag8\030\010 \001(\003\022\014\n\004tag9\030\t \001(\003\022\023\n\013last_upda" + "te\030\n \001(\003\022\r\n\005tag11\030\013 \001(\003\022\032\n\022last_player_u" + "pdate\030\014 \001(\003\"\342\001\n\rSegmentResult\022\n\n\002id\030\001 \001(" + "\003\022\020\n\010rider_id\030\002 \001(\003\022\031\n\021event_subgroup_id" + "\030\006 \001(\003\022\022\n\nfirst_name\030\007 \001(\t\022\021\n\tlast_name\030" + "\010 \001(\t\022\027\n\017finish_time_str\030\n \001(\t\022\022\n\nelapse" + "d_ms\030\013 \001(\003\022\022\n\npowermeter\030\014 \001(\005\022\016\n\006weight" + "\030\r \001(\005\022\r\n\005power\030\017 \001(\005\022\021\n\theartrate\030\023 \001(\005" + "\"z\n\016SegmentResults\022\020\n\010world_id\030\001 \001(\003\022\022\n\n" + "segment_id\030\002 \001(\003\022\031\n\021event_subgroup_id\030\003 " + "\001(\003\022\'\n\017segment_results\030\004 \003(\0132\016.SegmentRe" + "sult\"\021\n\017UnknownMessage1\"\020\n\016UnknownMessag" + "e\"\341\001\n\016ServerToClient\022\014\n\004tag1\030\001 \001(\005\022\020\n\010ri" + "der_id\030\002 \001(\005\022\022\n\nworld_time\030\003 \001(\003\022\r\n\005seqn" + "o\030\004 \001(\005\022#\n\rplayer_states\030\010 \003(\0132\014.PlayerS" + "tate\022\'\n\016player_updates\030\t \003(\0132\017.UnknownMe" + "ssage\022\r\n\005tag11\030\013 \001(\003\022\r\n\005tag17\030\021 \001(\003\022\020\n\010n" + "um_msgs\030\022 \001(\005\022\016\n\006msgnum\030\023 \001(\005\"u\n\017WorldAt" + "tributes\022\020\n\010world_id\030\001 \001(\005\022\014\n\004name\030\002 \001(\t" + "\022\014\n\004tag3\030\003 \001(\003\022\014\n\004tag5\030\004 \001(\003\022\022\n\nworld_ti" + "me\030\006 \001(\003\022\022\n\nclock_time\030\007 \001(\003\"$\n\016WorldAtt" + "ribute\022\022\n\nworld_time\030\002 \001(\003\"\251\001\n\025EventSubg" + "roupProtobuf\022\n\n\002id\030\001 \001(\005\022\014\n\004name\030\002 \001(\t\022\r" + "\n\005rules\030\010 \001(\005\022\r\n\005route\030\026 \001(\005\022\014\n\004laps\030\031 \001" + "(\005\022\025\n\rstartLocation\030\035 \001(\005\022\r\n\005label\030\036 \001(\005" + "\022\020\n\010paceType\030\037 \001(\005\022\022\n\njerseyHash\030$ \001(\005\"\361" + "\001\n\017RiderAttributes\022\n\n\002f2\030\002 \001(\005\022\n\n\002f3\030\003 \001" + "(\005\022;\n\020attributeMessage\030\004 \001(\0132!.RiderAttr" + "ibutes.AttributeMessage\022\017\n\007theirId\030\n \001(\005" + "\022\013\n\003f13\030\r \001(\005\032k\n\020AttributeMessage\022\014\n\004myI" + "d\030\001 \001(\005\022\017\n\007theirId\030\002 \001(\005\022\021\n\tfirstName\030\003 " + "\001(\t\022\020\n\010lastName\030\004 \001(\t\022\023\n\013countryCode\030\005 \001" + "(\005\"&\n\010Profiles\022\032\n\010profiles\030\001 \003(\0132\010.Profi" + "le\"\212\003\n\007Profile\022\n\n\002id\030\001 \001(\005\022\021\n\tfirstName\030" + "\004 \001(\t\022\020\n\010lastName\030\005 \001(\t\022\014\n\004male\030\006 \001(\005\022\016\n" + "\006weight\030\t \001(\005\022\020\n\010bodyType\030\014 \001(\005\022\023\n\013count" + "ryCode\030\" \001(\005\022\025\n\rtotalDistance\030# \001(\005\022\034\n\024t" + "otalDistanceClimbed\030$ \001(\005\022\032\n\022totalTimeIn" + "Minutes\030% \001(\005\022\026\n\016totalWattHours\030) \001(\005\022\016\n" + "\006height\030* \001(\005\022\035\n\025totalExperiencePoints\030." + " \001(\005\022\030\n\020achievementLevel\0301 \001(\005\022\023\n\013powerS" + "ource\0304 \001(\005\022\013\n\003age\0307 \001(\005\022\032\n\022launchedGame" + "Client\030l \001(\t\022\031\n\021currentActivityId\030m \001(\005b" + "\006proto3" +}; +static ::absl::once_flag descriptor_table_zwift_5fmessages_2eproto_once; +const ::_pbi::DescriptorTable descriptor_table_zwift_5fmessages_2eproto = { + false, + false, + 2327, + descriptor_table_protodef_zwift_5fmessages_2eproto, + "zwift_messages.proto", + &descriptor_table_zwift_5fmessages_2eproto_once, + nullptr, + 0, + 14, + schemas, + file_default_instances, + TableStruct_zwift_5fmessages_2eproto::offsets, + file_level_metadata_zwift_5fmessages_2eproto, + file_level_enum_descriptors_zwift_5fmessages_2eproto, + file_level_service_descriptors_zwift_5fmessages_2eproto, +}; + +// This function exists to be marked as weak. +// It can significantly speed up compilation by breaking up LLVM's SCC +// in the .pb.cc translation units. Large translation units see a +// reduction of more than 35% of walltime for optimized builds. Without +// the weak attribute all the messages in the file, including all the +// vtables and everything they use become part of the same SCC through +// a cycle like: +// GetMetadata -> descriptor table -> default instances -> +// vtables -> GetMetadata +// By adding a weak function here we break the connection from the +// individual vtables back into the descriptor table. +PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_zwift_5fmessages_2eproto_getter() { + return &descriptor_table_zwift_5fmessages_2eproto; +} +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 +static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_zwift_5fmessages_2eproto(&descriptor_table_zwift_5fmessages_2eproto); +// =================================================================== + +class PlayerState::_Internal { + public: +}; + +PlayerState::PlayerState(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:PlayerState) +} +PlayerState::PlayerState( + ::google::protobuf::Arena* arena, const PlayerState& from) + : PlayerState(arena) { + MergeFrom(from); +} +inline PROTOBUF_NDEBUG_INLINE PlayerState::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : _cached_size_{0} {} + +inline void PlayerState::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, worldtime_), + 0, + offsetof(Impl_, sport_) - + offsetof(Impl_, worldtime_) + + sizeof(Impl_::sport_)); +} +PlayerState::~PlayerState() { + // @@protoc_insertion_point(destructor:PlayerState) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void PlayerState::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void PlayerState::Clear() { +// @@protoc_insertion_point(message_clear_start:PlayerState) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&_impl_.worldtime_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.sport_) - + reinterpret_cast(&_impl_.worldtime_)) + sizeof(_impl_.sport_)); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* PlayerState::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<5, 26, 0, 0, 2> PlayerState::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 31, 248, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 2684551744, // skipmap + offsetof(decltype(_table_), field_entries), + 26, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + &_PlayerState_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // int32 id = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.id_), 63>(), + {8, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.id_)}}, + // int64 worldTime = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(PlayerState, _impl_.worldtime_), 63>(), + {16, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.worldtime_)}}, + // int32 distance = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.distance_), 63>(), + {24, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.distance_)}}, + // int32 roadTime = 4; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.roadtime_), 63>(), + {32, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.roadtime_)}}, + // int32 laps = 5; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.laps_), 63>(), + {40, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.laps_)}}, + // int32 speed = 6; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.speed_), 63>(), + {48, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.speed_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 roadPosition = 8; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.roadposition_), 63>(), + {64, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.roadposition_)}}, + // int32 cadenceUHz = 9; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.cadenceuhz_), 63>(), + {72, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.cadenceuhz_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 heartrate = 11; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.heartrate_), 63>(), + {88, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.heartrate_)}}, + // int32 power = 12; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.power_), 63>(), + {96, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.power_)}}, + // int64 heading = 13; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(PlayerState, _impl_.heading_), 63>(), + {104, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.heading_)}}, + // int32 lean = 14; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.lean_), 63>(), + {112, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.lean_)}}, + // int32 climbing = 15; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(PlayerState, _impl_.climbing_), 63>(), + {120, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.climbing_)}}, + // int32 time = 16; + {::_pbi::TcParser::FastV32S2, + {384, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.time_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 f19 = 19; + {::_pbi::TcParser::FastV32S2, + {408, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.f19_)}}, + // int32 f20 = 20; + {::_pbi::TcParser::FastV32S2, + {416, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.f20_)}}, + // int32 progress = 21; + {::_pbi::TcParser::FastV32S2, + {424, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.progress_)}}, + // int64 customisationId = 22; + {::_pbi::TcParser::FastV64S2, + {432, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.customisationid_)}}, + // int32 justWatching = 23; + {::_pbi::TcParser::FastV32S2, + {440, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.justwatching_)}}, + // int32 calories = 24; + {::_pbi::TcParser::FastV32S2, + {448, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.calories_)}}, + // float x = 25; + {::_pbi::TcParser::FastF32S2, + {461, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.x_)}}, + // float altitude = 26; + {::_pbi::TcParser::FastF32S2, + {469, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.altitude_)}}, + // float y = 27; + {::_pbi::TcParser::FastF32S2, + {477, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.y_)}}, + // int32 watchingRiderId = 28; + {::_pbi::TcParser::FastV32S2, + {480, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.watchingriderid_)}}, + // int32 groupId = 29; + {::_pbi::TcParser::FastV32S2, + {488, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.groupid_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int64 sport = 31; + {::_pbi::TcParser::FastV64S2, + {504, 63, 0, PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.sport_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // int32 id = 1; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int64 worldTime = 2; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.worldtime_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int32 distance = 3; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.distance_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 roadTime = 4; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.roadtime_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 laps = 5; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.laps_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 speed = 6; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.speed_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 roadPosition = 8; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.roadposition_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 cadenceUHz = 9; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.cadenceuhz_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 heartrate = 11; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.heartrate_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 power = 12; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.power_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int64 heading = 13; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.heading_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int32 lean = 14; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.lean_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 climbing = 15; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.climbing_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 time = 16; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.time_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 f19 = 19; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.f19_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 f20 = 20; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.f20_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 progress = 21; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.progress_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int64 customisationId = 22; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.customisationid_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int32 justWatching = 23; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.justwatching_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 calories = 24; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.calories_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // float x = 25; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.x_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kFloat)}, + // float altitude = 26; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.altitude_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kFloat)}, + // float y = 27; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.y_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kFloat)}, + // int32 watchingRiderId = 28; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.watchingriderid_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 groupId = 29; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.groupid_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int64 sport = 31; + {PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.sport_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + }}, + // no aux_entries + {{ + }}, +}; + +::uint8_t* PlayerState::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:PlayerState) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int32 id = 1; + if (this->_internal_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this->_internal_id(), target); + } + + // int64 worldTime = 2; + if (this->_internal_worldtime() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<2>( + stream, this->_internal_worldtime(), target); + } + + // int32 distance = 3; + if (this->_internal_distance() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<3>( + stream, this->_internal_distance(), target); + } + + // int32 roadTime = 4; + if (this->_internal_roadtime() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<4>( + stream, this->_internal_roadtime(), target); + } + + // int32 laps = 5; + if (this->_internal_laps() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<5>( + stream, this->_internal_laps(), target); + } + + // int32 speed = 6; + if (this->_internal_speed() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<6>( + stream, this->_internal_speed(), target); + } + + // int32 roadPosition = 8; + if (this->_internal_roadposition() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<8>( + stream, this->_internal_roadposition(), target); + } + + // int32 cadenceUHz = 9; + if (this->_internal_cadenceuhz() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<9>( + stream, this->_internal_cadenceuhz(), target); + } + + // int32 heartrate = 11; + if (this->_internal_heartrate() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<11>( + stream, this->_internal_heartrate(), target); + } + + // int32 power = 12; + if (this->_internal_power() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<12>( + stream, this->_internal_power(), target); + } + + // int64 heading = 13; + if (this->_internal_heading() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<13>( + stream, this->_internal_heading(), target); + } + + // int32 lean = 14; + if (this->_internal_lean() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<14>( + stream, this->_internal_lean(), target); + } + + // int32 climbing = 15; + if (this->_internal_climbing() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<15>( + stream, this->_internal_climbing(), target); + } + + // int32 time = 16; + if (this->_internal_time() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 16, this->_internal_time(), target); + } + + // int32 f19 = 19; + if (this->_internal_f19() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 19, this->_internal_f19(), target); + } + + // int32 f20 = 20; + if (this->_internal_f20() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 20, this->_internal_f20(), target); + } + + // int32 progress = 21; + if (this->_internal_progress() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 21, this->_internal_progress(), target); + } + + // int64 customisationId = 22; + if (this->_internal_customisationid() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray( + 22, this->_internal_customisationid(), target); + } + + // int32 justWatching = 23; + if (this->_internal_justwatching() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 23, this->_internal_justwatching(), target); + } + + // int32 calories = 24; + if (this->_internal_calories() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 24, this->_internal_calories(), target); + } + + // float x = 25; + static_assert(sizeof(::uint32_t) == sizeof(float), + "Code assumes ::uint32_t and float are the same size."); + float tmp_x = this->_internal_x(); + ::uint32_t raw_x; + memcpy(&raw_x, &tmp_x, sizeof(tmp_x)); + if (raw_x != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteFloatToArray( + 25, this->_internal_x(), target); + } + + // float altitude = 26; + static_assert(sizeof(::uint32_t) == sizeof(float), + "Code assumes ::uint32_t and float are the same size."); + float tmp_altitude = this->_internal_altitude(); + ::uint32_t raw_altitude; + memcpy(&raw_altitude, &tmp_altitude, sizeof(tmp_altitude)); + if (raw_altitude != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteFloatToArray( + 26, this->_internal_altitude(), target); + } + + // float y = 27; + static_assert(sizeof(::uint32_t) == sizeof(float), + "Code assumes ::uint32_t and float are the same size."); + float tmp_y = this->_internal_y(); + ::uint32_t raw_y; + memcpy(&raw_y, &tmp_y, sizeof(tmp_y)); + if (raw_y != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteFloatToArray( + 27, this->_internal_y(), target); + } + + // int32 watchingRiderId = 28; + if (this->_internal_watchingriderid() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 28, this->_internal_watchingriderid(), target); + } + + // int32 groupId = 29; + if (this->_internal_groupid() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 29, this->_internal_groupid(), target); + } + + // int64 sport = 31; + if (this->_internal_sport() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray( + 31, this->_internal_sport(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:PlayerState) + return target; +} + +::size_t PlayerState::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:PlayerState) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int64 worldTime = 2; + if (this->_internal_worldtime() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_worldtime()); + } + + // int32 id = 1; + if (this->_internal_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_id()); + } + + // int32 distance = 3; + if (this->_internal_distance() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_distance()); + } + + // int32 roadTime = 4; + if (this->_internal_roadtime() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_roadtime()); + } + + // int32 laps = 5; + if (this->_internal_laps() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_laps()); + } + + // int32 speed = 6; + if (this->_internal_speed() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_speed()); + } + + // int32 roadPosition = 8; + if (this->_internal_roadposition() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_roadposition()); + } + + // int32 cadenceUHz = 9; + if (this->_internal_cadenceuhz() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_cadenceuhz()); + } + + // int32 heartrate = 11; + if (this->_internal_heartrate() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_heartrate()); + } + + // int64 heading = 13; + if (this->_internal_heading() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_heading()); + } + + // int32 power = 12; + if (this->_internal_power() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_power()); + } + + // int32 lean = 14; + if (this->_internal_lean() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_lean()); + } + + // int32 climbing = 15; + if (this->_internal_climbing() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_climbing()); + } + + // int32 time = 16; + if (this->_internal_time() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_time()); + } + + // int32 f19 = 19; + if (this->_internal_f19() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_f19()); + } + + // int32 f20 = 20; + if (this->_internal_f20() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_f20()); + } + + // int64 customisationId = 22; + if (this->_internal_customisationid() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int64Size( + this->_internal_customisationid()); + } + + // int32 progress = 21; + if (this->_internal_progress() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_progress()); + } + + // int32 justWatching = 23; + if (this->_internal_justwatching() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_justwatching()); + } + + // int32 calories = 24; + if (this->_internal_calories() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_calories()); + } + + // float x = 25; + static_assert(sizeof(::uint32_t) == sizeof(float), + "Code assumes ::uint32_t and float are the same size."); + float tmp_x = this->_internal_x(); + ::uint32_t raw_x; + memcpy(&raw_x, &tmp_x, sizeof(tmp_x)); + if (raw_x != 0) { + total_size += 6; + } + + // float altitude = 26; + static_assert(sizeof(::uint32_t) == sizeof(float), + "Code assumes ::uint32_t and float are the same size."); + float tmp_altitude = this->_internal_altitude(); + ::uint32_t raw_altitude; + memcpy(&raw_altitude, &tmp_altitude, sizeof(tmp_altitude)); + if (raw_altitude != 0) { + total_size += 6; + } + + // float y = 27; + static_assert(sizeof(::uint32_t) == sizeof(float), + "Code assumes ::uint32_t and float are the same size."); + float tmp_y = this->_internal_y(); + ::uint32_t raw_y; + memcpy(&raw_y, &tmp_y, sizeof(tmp_y)); + if (raw_y != 0) { + total_size += 6; + } + + // int32 watchingRiderId = 28; + if (this->_internal_watchingriderid() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_watchingriderid()); + } + + // int32 groupId = 29; + if (this->_internal_groupid() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_groupid()); + } + + // int64 sport = 31; + if (this->_internal_sport() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int64Size( + this->_internal_sport()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData PlayerState::_class_data_ = { + PlayerState::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* PlayerState::GetClassData() const { + return &_class_data_; +} + +void PlayerState::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:PlayerState) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_worldtime() != 0) { + _this->_internal_set_worldtime(from._internal_worldtime()); + } + if (from._internal_id() != 0) { + _this->_internal_set_id(from._internal_id()); + } + if (from._internal_distance() != 0) { + _this->_internal_set_distance(from._internal_distance()); + } + if (from._internal_roadtime() != 0) { + _this->_internal_set_roadtime(from._internal_roadtime()); + } + if (from._internal_laps() != 0) { + _this->_internal_set_laps(from._internal_laps()); + } + if (from._internal_speed() != 0) { + _this->_internal_set_speed(from._internal_speed()); + } + if (from._internal_roadposition() != 0) { + _this->_internal_set_roadposition(from._internal_roadposition()); + } + if (from._internal_cadenceuhz() != 0) { + _this->_internal_set_cadenceuhz(from._internal_cadenceuhz()); + } + if (from._internal_heartrate() != 0) { + _this->_internal_set_heartrate(from._internal_heartrate()); + } + if (from._internal_heading() != 0) { + _this->_internal_set_heading(from._internal_heading()); + } + if (from._internal_power() != 0) { + _this->_internal_set_power(from._internal_power()); + } + if (from._internal_lean() != 0) { + _this->_internal_set_lean(from._internal_lean()); + } + if (from._internal_climbing() != 0) { + _this->_internal_set_climbing(from._internal_climbing()); + } + if (from._internal_time() != 0) { + _this->_internal_set_time(from._internal_time()); + } + if (from._internal_f19() != 0) { + _this->_internal_set_f19(from._internal_f19()); + } + if (from._internal_f20() != 0) { + _this->_internal_set_f20(from._internal_f20()); + } + if (from._internal_customisationid() != 0) { + _this->_internal_set_customisationid(from._internal_customisationid()); + } + if (from._internal_progress() != 0) { + _this->_internal_set_progress(from._internal_progress()); + } + if (from._internal_justwatching() != 0) { + _this->_internal_set_justwatching(from._internal_justwatching()); + } + if (from._internal_calories() != 0) { + _this->_internal_set_calories(from._internal_calories()); + } + static_assert(sizeof(::uint32_t) == sizeof(float), + "Code assumes ::uint32_t and float are the same size."); + float tmp_x = from._internal_x(); + ::uint32_t raw_x; + memcpy(&raw_x, &tmp_x, sizeof(tmp_x)); + if (raw_x != 0) { + _this->_internal_set_x(from._internal_x()); + } + static_assert(sizeof(::uint32_t) == sizeof(float), + "Code assumes ::uint32_t and float are the same size."); + float tmp_altitude = from._internal_altitude(); + ::uint32_t raw_altitude; + memcpy(&raw_altitude, &tmp_altitude, sizeof(tmp_altitude)); + if (raw_altitude != 0) { + _this->_internal_set_altitude(from._internal_altitude()); + } + static_assert(sizeof(::uint32_t) == sizeof(float), + "Code assumes ::uint32_t and float are the same size."); + float tmp_y = from._internal_y(); + ::uint32_t raw_y; + memcpy(&raw_y, &tmp_y, sizeof(tmp_y)); + if (raw_y != 0) { + _this->_internal_set_y(from._internal_y()); + } + if (from._internal_watchingriderid() != 0) { + _this->_internal_set_watchingriderid(from._internal_watchingriderid()); + } + if (from._internal_groupid() != 0) { + _this->_internal_set_groupid(from._internal_groupid()); + } + if (from._internal_sport() != 0) { + _this->_internal_set_sport(from._internal_sport()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void PlayerState::CopyFrom(const PlayerState& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:PlayerState) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool PlayerState::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* PlayerState::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void PlayerState::InternalSwap(PlayerState* PROTOBUF_RESTRICT other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.sport_) + + sizeof(PlayerState::_impl_.sport_) + - PROTOBUF_FIELD_OFFSET(PlayerState, _impl_.worldtime_)>( + reinterpret_cast(&_impl_.worldtime_), + reinterpret_cast(&other->_impl_.worldtime_)); +} + +::google::protobuf::Metadata PlayerState::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[0]); +} +// =================================================================== + +class ClientToServer::_Internal { + public: + using HasBits = decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_._has_bits_); + static const ::PlayerState& state(const ClientToServer* msg); + static void set_has_state(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } +}; + +const ::PlayerState& ClientToServer::_Internal::state(const ClientToServer* msg) { + return *msg->_impl_.state_; +} +ClientToServer::ClientToServer(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:ClientToServer) +} +inline PROTOBUF_NDEBUG_INLINE ClientToServer::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : _has_bits_{from._has_bits_}, + _cached_size_{0} {} + +ClientToServer::ClientToServer( + ::google::protobuf::Arena* arena, + const ClientToServer& from) + : ::google::protobuf::Message(arena) { + ClientToServer* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.state_ = (cached_has_bits & 0x00000001u) + ? CreateMaybeMessage<::PlayerState>(arena, *from._impl_.state_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, connected_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, connected_), + offsetof(Impl_, seqno_) - + offsetof(Impl_, connected_) + + sizeof(Impl_::seqno_)); + + // @@protoc_insertion_point(copy_constructor:ClientToServer) +} +inline PROTOBUF_NDEBUG_INLINE ClientToServer::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : _cached_size_{0} {} + +inline void ClientToServer::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, state_), + 0, + offsetof(Impl_, seqno_) - + offsetof(Impl_, state_) + + sizeof(Impl_::seqno_)); +} +ClientToServer::~ClientToServer() { + // @@protoc_insertion_point(destructor:ClientToServer) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void ClientToServer::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + delete _impl_.state_; + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void ClientToServer::Clear() { +// @@protoc_insertion_point(message_clear_start:ClientToServer) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + ABSL_DCHECK(_impl_.state_ != nullptr); + _impl_.state_->Clear(); + } + ::memset(&_impl_.connected_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.seqno_) - + reinterpret_cast(&_impl_.connected_)) + sizeof(_impl_.seqno_)); + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* ClientToServer::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<4, 10, 1, 0, 2> ClientToServer::_table_ = { + { + PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_._has_bits_), + 0, // no _extensions_ + 12, 120, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294963248, // skipmap + offsetof(decltype(_table_), field_entries), + 10, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + &_ClientToServer_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // int32 connected = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ClientToServer, _impl_.connected_), 63>(), + {8, 63, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.connected_)}}, + // int32 rider_id = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ClientToServer, _impl_.rider_id_), 63>(), + {16, 63, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.rider_id_)}}, + // int64 world_time = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ClientToServer, _impl_.world_time_), 63>(), + {24, 63, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.world_time_)}}, + // int32 seqno = 4; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ClientToServer, _impl_.seqno_), 63>(), + {32, 63, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.seqno_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // .PlayerState state = 7; + {::_pbi::TcParser::FastMtS1, + {58, 0, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.state_)}}, + // int64 tag8 = 8; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ClientToServer, _impl_.tag8_), 63>(), + {64, 63, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.tag8_)}}, + // int64 tag9 = 9; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ClientToServer, _impl_.tag9_), 63>(), + {72, 63, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.tag9_)}}, + // int64 last_update = 10; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ClientToServer, _impl_.last_update_), 63>(), + {80, 63, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.last_update_)}}, + // int64 tag11 = 11; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ClientToServer, _impl_.tag11_), 63>(), + {88, 63, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.tag11_)}}, + // int64 last_player_update = 12; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ClientToServer, _impl_.last_player_update_), 63>(), + {96, 63, 0, PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.last_player_update_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // int32 connected = 1; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.connected_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 rider_id = 2; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.rider_id_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int64 world_time = 3; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.world_time_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int32 seqno = 4; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.seqno_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // .PlayerState state = 7; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.state_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // int64 tag8 = 8; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.tag8_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 tag9 = 9; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.tag9_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 last_update = 10; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.last_update_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 tag11 = 11; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.tag11_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 last_player_update = 12; + {PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.last_player_update_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + }}, {{ + {::_pbi::TcParser::GetTable<::PlayerState>()}, + }}, {{ + }}, +}; + +::uint8_t* ClientToServer::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:ClientToServer) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int32 connected = 1; + if (this->_internal_connected() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this->_internal_connected(), target); + } + + // int32 rider_id = 2; + if (this->_internal_rider_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this->_internal_rider_id(), target); + } + + // int64 world_time = 3; + if (this->_internal_world_time() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<3>( + stream, this->_internal_world_time(), target); + } + + // int32 seqno = 4; + if (this->_internal_seqno() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<4>( + stream, this->_internal_seqno(), target); + } + + cached_has_bits = _impl_._has_bits_[0]; + // .PlayerState state = 7; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 7, _Internal::state(this), + _Internal::state(this).GetCachedSize(), target, stream); + } + + // int64 tag8 = 8; + if (this->_internal_tag8() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<8>( + stream, this->_internal_tag8(), target); + } + + // int64 tag9 = 9; + if (this->_internal_tag9() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<9>( + stream, this->_internal_tag9(), target); + } + + // int64 last_update = 10; + if (this->_internal_last_update() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<10>( + stream, this->_internal_last_update(), target); + } + + // int64 tag11 = 11; + if (this->_internal_tag11() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<11>( + stream, this->_internal_tag11(), target); + } + + // int64 last_player_update = 12; + if (this->_internal_last_player_update() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<12>( + stream, this->_internal_last_player_update(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:ClientToServer) + return target; +} + +::size_t ClientToServer::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:ClientToServer) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // .PlayerState state = 7; + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + total_size += + 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.state_); + } + + // int32 connected = 1; + if (this->_internal_connected() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_connected()); + } + + // int32 rider_id = 2; + if (this->_internal_rider_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_rider_id()); + } + + // int64 world_time = 3; + if (this->_internal_world_time() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_world_time()); + } + + // int64 tag8 = 8; + if (this->_internal_tag8() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_tag8()); + } + + // int64 tag9 = 9; + if (this->_internal_tag9() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_tag9()); + } + + // int64 last_update = 10; + if (this->_internal_last_update() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_last_update()); + } + + // int64 tag11 = 11; + if (this->_internal_tag11() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_tag11()); + } + + // int64 last_player_update = 12; + if (this->_internal_last_player_update() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_last_player_update()); + } + + // int32 seqno = 4; + if (this->_internal_seqno() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_seqno()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData ClientToServer::_class_data_ = { + ClientToServer::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* ClientToServer::GetClassData() const { + return &_class_data_; +} + +void ClientToServer::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:ClientToServer) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) { + _this->_internal_mutable_state()->::PlayerState::MergeFrom( + from._internal_state()); + } + if (from._internal_connected() != 0) { + _this->_internal_set_connected(from._internal_connected()); + } + if (from._internal_rider_id() != 0) { + _this->_internal_set_rider_id(from._internal_rider_id()); + } + if (from._internal_world_time() != 0) { + _this->_internal_set_world_time(from._internal_world_time()); + } + if (from._internal_tag8() != 0) { + _this->_internal_set_tag8(from._internal_tag8()); + } + if (from._internal_tag9() != 0) { + _this->_internal_set_tag9(from._internal_tag9()); + } + if (from._internal_last_update() != 0) { + _this->_internal_set_last_update(from._internal_last_update()); + } + if (from._internal_tag11() != 0) { + _this->_internal_set_tag11(from._internal_tag11()); + } + if (from._internal_last_player_update() != 0) { + _this->_internal_set_last_player_update(from._internal_last_player_update()); + } + if (from._internal_seqno() != 0) { + _this->_internal_set_seqno(from._internal_seqno()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void ClientToServer::CopyFrom(const ClientToServer& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:ClientToServer) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool ClientToServer::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* ClientToServer::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void ClientToServer::InternalSwap(ClientToServer* PROTOBUF_RESTRICT other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.seqno_) + + sizeof(ClientToServer::_impl_.seqno_) + - PROTOBUF_FIELD_OFFSET(ClientToServer, _impl_.state_)>( + reinterpret_cast(&_impl_.state_), + reinterpret_cast(&other->_impl_.state_)); +} + +::google::protobuf::Metadata ClientToServer::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[1]); +} +// =================================================================== + +class SegmentResult::_Internal { + public: +}; + +SegmentResult::SegmentResult(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:SegmentResult) +} +inline PROTOBUF_NDEBUG_INLINE SegmentResult::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : first_name_(arena, from.first_name_), + last_name_(arena, from.last_name_), + finish_time_str_(arena, from.finish_time_str_), + _cached_size_{0} {} + +SegmentResult::SegmentResult( + ::google::protobuf::Arena* arena, + const SegmentResult& from) + : ::google::protobuf::Message(arena) { + SegmentResult* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, id_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, id_), + offsetof(Impl_, heartrate_) - + offsetof(Impl_, id_) + + sizeof(Impl_::heartrate_)); + + // @@protoc_insertion_point(copy_constructor:SegmentResult) +} +inline PROTOBUF_NDEBUG_INLINE SegmentResult::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : first_name_(arena), + last_name_(arena), + finish_time_str_(arena), + _cached_size_{0} {} + +inline void SegmentResult::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, id_), + 0, + offsetof(Impl_, heartrate_) - + offsetof(Impl_, id_) + + sizeof(Impl_::heartrate_)); +} +SegmentResult::~SegmentResult() { + // @@protoc_insertion_point(destructor:SegmentResult) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void SegmentResult::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.first_name_.Destroy(); + _impl_.last_name_.Destroy(); + _impl_.finish_time_str_.Destroy(); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void SegmentResult::Clear() { +// @@protoc_insertion_point(message_clear_start:SegmentResult) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.first_name_.ClearToEmpty(); + _impl_.last_name_.ClearToEmpty(); + _impl_.finish_time_str_.ClearToEmpty(); + ::memset(&_impl_.id_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.heartrate_) - + reinterpret_cast(&_impl_.id_)) + sizeof(_impl_.heartrate_)); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* SegmentResult::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<4, 11, 0, 64, 2> SegmentResult::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 19, 120, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294680860, // skipmap + offsetof(decltype(_table_), field_entries), + 11, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + &_SegmentResult_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // int64 id = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(SegmentResult, _impl_.id_), 63>(), + {8, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.id_)}}, + // int64 rider_id = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(SegmentResult, _impl_.rider_id_), 63>(), + {16, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.rider_id_)}}, + // int32 heartrate = 19; + {::_pbi::TcParser::FastV32S2, + {408, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.heartrate_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // int64 event_subgroup_id = 6; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(SegmentResult, _impl_.event_subgroup_id_), 63>(), + {48, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.event_subgroup_id_)}}, + // string first_name = 7; + {::_pbi::TcParser::FastUS1, + {58, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.first_name_)}}, + // string last_name = 8; + {::_pbi::TcParser::FastUS1, + {66, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.last_name_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // string finish_time_str = 10; + {::_pbi::TcParser::FastUS1, + {82, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.finish_time_str_)}}, + // int64 elapsed_ms = 11; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(SegmentResult, _impl_.elapsed_ms_), 63>(), + {88, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.elapsed_ms_)}}, + // int32 powermeter = 12; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(SegmentResult, _impl_.powermeter_), 63>(), + {96, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.powermeter_)}}, + // int32 weight = 13; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(SegmentResult, _impl_.weight_), 63>(), + {104, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.weight_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 power = 15; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(SegmentResult, _impl_.power_), 63>(), + {120, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.power_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // int64 id = 1; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 rider_id = 2; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.rider_id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 event_subgroup_id = 6; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.event_subgroup_id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // string first_name = 7; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.first_name_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string last_name = 8; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.last_name_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string finish_time_str = 10; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.finish_time_str_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // int64 elapsed_ms = 11; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.elapsed_ms_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int32 powermeter = 12; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.powermeter_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 weight = 13; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.weight_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 power = 15; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.power_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 heartrate = 19; + {PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.heartrate_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + }}, + // no aux_entries + {{ + "\15\0\0\0\12\11\17\0\0\0\0\0\0\0\0\0" + "SegmentResult" + "first_name" + "last_name" + "finish_time_str" + }}, +}; + +::uint8_t* SegmentResult::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:SegmentResult) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int64 id = 1; + if (this->_internal_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<1>( + stream, this->_internal_id(), target); + } + + // int64 rider_id = 2; + if (this->_internal_rider_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<2>( + stream, this->_internal_rider_id(), target); + } + + // int64 event_subgroup_id = 6; + if (this->_internal_event_subgroup_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<6>( + stream, this->_internal_event_subgroup_id(), target); + } + + // string first_name = 7; + if (!this->_internal_first_name().empty()) { + const std::string& _s = this->_internal_first_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "SegmentResult.first_name"); + target = stream->WriteStringMaybeAliased(7, _s, target); + } + + // string last_name = 8; + if (!this->_internal_last_name().empty()) { + const std::string& _s = this->_internal_last_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "SegmentResult.last_name"); + target = stream->WriteStringMaybeAliased(8, _s, target); + } + + // string finish_time_str = 10; + if (!this->_internal_finish_time_str().empty()) { + const std::string& _s = this->_internal_finish_time_str(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "SegmentResult.finish_time_str"); + target = stream->WriteStringMaybeAliased(10, _s, target); + } + + // int64 elapsed_ms = 11; + if (this->_internal_elapsed_ms() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<11>( + stream, this->_internal_elapsed_ms(), target); + } + + // int32 powermeter = 12; + if (this->_internal_powermeter() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<12>( + stream, this->_internal_powermeter(), target); + } + + // int32 weight = 13; + if (this->_internal_weight() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<13>( + stream, this->_internal_weight(), target); + } + + // int32 power = 15; + if (this->_internal_power() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<15>( + stream, this->_internal_power(), target); + } + + // int32 heartrate = 19; + if (this->_internal_heartrate() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 19, this->_internal_heartrate(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:SegmentResult) + return target; +} + +::size_t SegmentResult::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:SegmentResult) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string first_name = 7; + if (!this->_internal_first_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_first_name()); + } + + // string last_name = 8; + if (!this->_internal_last_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_last_name()); + } + + // string finish_time_str = 10; + if (!this->_internal_finish_time_str().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_finish_time_str()); + } + + // int64 id = 1; + if (this->_internal_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_id()); + } + + // int64 rider_id = 2; + if (this->_internal_rider_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_rider_id()); + } + + // int64 event_subgroup_id = 6; + if (this->_internal_event_subgroup_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_event_subgroup_id()); + } + + // int64 elapsed_ms = 11; + if (this->_internal_elapsed_ms() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_elapsed_ms()); + } + + // int32 powermeter = 12; + if (this->_internal_powermeter() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_powermeter()); + } + + // int32 weight = 13; + if (this->_internal_weight() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_weight()); + } + + // int32 power = 15; + if (this->_internal_power() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_power()); + } + + // int32 heartrate = 19; + if (this->_internal_heartrate() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_heartrate()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData SegmentResult::_class_data_ = { + SegmentResult::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* SegmentResult::GetClassData() const { + return &_class_data_; +} + +void SegmentResult::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:SegmentResult) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_first_name().empty()) { + _this->_internal_set_first_name(from._internal_first_name()); + } + if (!from._internal_last_name().empty()) { + _this->_internal_set_last_name(from._internal_last_name()); + } + if (!from._internal_finish_time_str().empty()) { + _this->_internal_set_finish_time_str(from._internal_finish_time_str()); + } + if (from._internal_id() != 0) { + _this->_internal_set_id(from._internal_id()); + } + if (from._internal_rider_id() != 0) { + _this->_internal_set_rider_id(from._internal_rider_id()); + } + if (from._internal_event_subgroup_id() != 0) { + _this->_internal_set_event_subgroup_id(from._internal_event_subgroup_id()); + } + if (from._internal_elapsed_ms() != 0) { + _this->_internal_set_elapsed_ms(from._internal_elapsed_ms()); + } + if (from._internal_powermeter() != 0) { + _this->_internal_set_powermeter(from._internal_powermeter()); + } + if (from._internal_weight() != 0) { + _this->_internal_set_weight(from._internal_weight()); + } + if (from._internal_power() != 0) { + _this->_internal_set_power(from._internal_power()); + } + if (from._internal_heartrate() != 0) { + _this->_internal_set_heartrate(from._internal_heartrate()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void SegmentResult::CopyFrom(const SegmentResult& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:SegmentResult) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool SegmentResult::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* SegmentResult::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void SegmentResult::InternalSwap(SegmentResult* PROTOBUF_RESTRICT other) { + using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.first_name_, &other->_impl_.first_name_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.last_name_, &other->_impl_.last_name_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.finish_time_str_, &other->_impl_.finish_time_str_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.heartrate_) + + sizeof(SegmentResult::_impl_.heartrate_) + - PROTOBUF_FIELD_OFFSET(SegmentResult, _impl_.id_)>( + reinterpret_cast(&_impl_.id_), + reinterpret_cast(&other->_impl_.id_)); +} + +::google::protobuf::Metadata SegmentResult::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[2]); +} +// =================================================================== + +class SegmentResults::_Internal { + public: +}; + +SegmentResults::SegmentResults(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:SegmentResults) +} +inline PROTOBUF_NDEBUG_INLINE SegmentResults::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : segment_results_{visibility, arena, from.segment_results_}, + _cached_size_{0} {} + +SegmentResults::SegmentResults( + ::google::protobuf::Arena* arena, + const SegmentResults& from) + : ::google::protobuf::Message(arena) { + SegmentResults* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, world_id_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, world_id_), + offsetof(Impl_, event_subgroup_id_) - + offsetof(Impl_, world_id_) + + sizeof(Impl_::event_subgroup_id_)); + + // @@protoc_insertion_point(copy_constructor:SegmentResults) +} +inline PROTOBUF_NDEBUG_INLINE SegmentResults::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : segment_results_{visibility, arena}, + _cached_size_{0} {} + +inline void SegmentResults::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, world_id_), + 0, + offsetof(Impl_, event_subgroup_id_) - + offsetof(Impl_, world_id_) + + sizeof(Impl_::event_subgroup_id_)); +} +SegmentResults::~SegmentResults() { + // @@protoc_insertion_point(destructor:SegmentResults) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void SegmentResults::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void SegmentResults::Clear() { +// @@protoc_insertion_point(message_clear_start:SegmentResults) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.segment_results_.Clear(); + ::memset(&_impl_.world_id_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.event_subgroup_id_) - + reinterpret_cast(&_impl_.world_id_)) + sizeof(_impl_.event_subgroup_id_)); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* SegmentResults::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 4, 1, 0, 2> SegmentResults::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 4, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967280, // skipmap + offsetof(decltype(_table_), field_entries), + 4, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + &_SegmentResults_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + // repeated .SegmentResult segment_results = 4; + {::_pbi::TcParser::FastMtR1, + {34, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.segment_results_)}}, + // int64 world_id = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(SegmentResults, _impl_.world_id_), 63>(), + {8, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.world_id_)}}, + // int64 segment_id = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(SegmentResults, _impl_.segment_id_), 63>(), + {16, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.segment_id_)}}, + // int64 event_subgroup_id = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(SegmentResults, _impl_.event_subgroup_id_), 63>(), + {24, 63, 0, PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.event_subgroup_id_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // int64 world_id = 1; + {PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.world_id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 segment_id = 2; + {PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.segment_id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 event_subgroup_id = 3; + {PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.event_subgroup_id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // repeated .SegmentResult segment_results = 4; + {PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.segment_results_), 0, 0, + (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, {{ + {::_pbi::TcParser::GetTable<::SegmentResult>()}, + }}, {{ + }}, +}; + +::uint8_t* SegmentResults::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:SegmentResults) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int64 world_id = 1; + if (this->_internal_world_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<1>( + stream, this->_internal_world_id(), target); + } + + // int64 segment_id = 2; + if (this->_internal_segment_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<2>( + stream, this->_internal_segment_id(), target); + } + + // int64 event_subgroup_id = 3; + if (this->_internal_event_subgroup_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<3>( + stream, this->_internal_event_subgroup_id(), target); + } + + // repeated .SegmentResult segment_results = 4; + for (unsigned i = 0, + n = static_cast(this->_internal_segment_results_size()); i < n; i++) { + const auto& repfield = this->_internal_segment_results().Get(i); + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessage(4, repfield, repfield.GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:SegmentResults) + return target; +} + +::size_t SegmentResults::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:SegmentResults) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .SegmentResult segment_results = 4; + total_size += 1UL * this->_internal_segment_results_size(); + for (const auto& msg : this->_internal_segment_results()) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + // int64 world_id = 1; + if (this->_internal_world_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_world_id()); + } + + // int64 segment_id = 2; + if (this->_internal_segment_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_segment_id()); + } + + // int64 event_subgroup_id = 3; + if (this->_internal_event_subgroup_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_event_subgroup_id()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData SegmentResults::_class_data_ = { + SegmentResults::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* SegmentResults::GetClassData() const { + return &_class_data_; +} + +void SegmentResults::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:SegmentResults) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_segment_results()->MergeFrom( + from._internal_segment_results()); + if (from._internal_world_id() != 0) { + _this->_internal_set_world_id(from._internal_world_id()); + } + if (from._internal_segment_id() != 0) { + _this->_internal_set_segment_id(from._internal_segment_id()); + } + if (from._internal_event_subgroup_id() != 0) { + _this->_internal_set_event_subgroup_id(from._internal_event_subgroup_id()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void SegmentResults::CopyFrom(const SegmentResults& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:SegmentResults) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool SegmentResults::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* SegmentResults::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void SegmentResults::InternalSwap(SegmentResults* PROTOBUF_RESTRICT other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.segment_results_.InternalSwap(&other->_impl_.segment_results_); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.event_subgroup_id_) + + sizeof(SegmentResults::_impl_.event_subgroup_id_) + - PROTOBUF_FIELD_OFFSET(SegmentResults, _impl_.world_id_)>( + reinterpret_cast(&_impl_.world_id_), + reinterpret_cast(&other->_impl_.world_id_)); +} + +::google::protobuf::Metadata SegmentResults::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[3]); +} +// =================================================================== + +class UnknownMessage1::_Internal { + public: +}; + +UnknownMessage1::UnknownMessage1(::google::protobuf::Arena* arena) + : ::google::protobuf::internal::ZeroFieldsBase(arena) { + // @@protoc_insertion_point(arena_constructor:UnknownMessage1) +} +UnknownMessage1::UnknownMessage1( + ::google::protobuf::Arena* arena, + const UnknownMessage1& from) + : ::google::protobuf::internal::ZeroFieldsBase(arena) { + UnknownMessage1* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:UnknownMessage1) +} + + + + + + + + + +::google::protobuf::Metadata UnknownMessage1::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[4]); +} +// =================================================================== + +class UnknownMessage::_Internal { + public: +}; + +UnknownMessage::UnknownMessage(::google::protobuf::Arena* arena) + : ::google::protobuf::internal::ZeroFieldsBase(arena) { + // @@protoc_insertion_point(arena_constructor:UnknownMessage) +} +UnknownMessage::UnknownMessage( + ::google::protobuf::Arena* arena, + const UnknownMessage& from) + : ::google::protobuf::internal::ZeroFieldsBase(arena) { + UnknownMessage* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + + // @@protoc_insertion_point(copy_constructor:UnknownMessage) +} + + + + + + + + + +::google::protobuf::Metadata UnknownMessage::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[5]); +} +// =================================================================== + +class ServerToClient::_Internal { + public: +}; + +ServerToClient::ServerToClient(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:ServerToClient) +} +inline PROTOBUF_NDEBUG_INLINE ServerToClient::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : player_states_{visibility, arena, from.player_states_}, + player_updates_{visibility, arena, from.player_updates_}, + _cached_size_{0} {} + +ServerToClient::ServerToClient( + ::google::protobuf::Arena* arena, + const ServerToClient& from) + : ::google::protobuf::Message(arena) { + ServerToClient* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, tag1_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, tag1_), + offsetof(Impl_, msgnum_) - + offsetof(Impl_, tag1_) + + sizeof(Impl_::msgnum_)); + + // @@protoc_insertion_point(copy_constructor:ServerToClient) +} +inline PROTOBUF_NDEBUG_INLINE ServerToClient::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : player_states_{visibility, arena}, + player_updates_{visibility, arena}, + _cached_size_{0} {} + +inline void ServerToClient::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, tag1_), + 0, + offsetof(Impl_, msgnum_) - + offsetof(Impl_, tag1_) + + sizeof(Impl_::msgnum_)); +} +ServerToClient::~ServerToClient() { + // @@protoc_insertion_point(destructor:ServerToClient) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void ServerToClient::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void ServerToClient::Clear() { +// @@protoc_insertion_point(message_clear_start:ServerToClient) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.player_states_.Clear(); + _impl_.player_updates_.Clear(); + ::memset(&_impl_.tag1_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.msgnum_) - + reinterpret_cast(&_impl_.tag1_)) + sizeof(_impl_.msgnum_)); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* ServerToClient::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<4, 10, 2, 0, 2> ServerToClient::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 19, 120, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294507120, // skipmap + offsetof(decltype(_table_), field_entries), + 10, // num_field_entries + 2, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + &_ServerToClient_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // int32 tag1 = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ServerToClient, _impl_.tag1_), 63>(), + {8, 63, 0, PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.tag1_)}}, + // int32 rider_id = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ServerToClient, _impl_.rider_id_), 63>(), + {16, 63, 0, PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.rider_id_)}}, + // int64 world_time = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ServerToClient, _impl_.world_time_), 63>(), + {24, 63, 0, PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.world_time_)}}, + // int32 seqno = 4; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(ServerToClient, _impl_.seqno_), 63>(), + {32, 63, 0, PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.seqno_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // repeated .PlayerState player_states = 8; + {::_pbi::TcParser::FastMtR1, + {66, 63, 0, PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.player_states_)}}, + // repeated .UnknownMessage player_updates = 9; + {::_pbi::TcParser::FastMdR1, + {74, 63, 1, PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.player_updates_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int64 tag11 = 11; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(ServerToClient, _impl_.tag11_), 63>(), + {88, 63, 0, PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.tag11_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // int32 tag1 = 1; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.tag1_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 rider_id = 2; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.rider_id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int64 world_time = 3; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.world_time_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int32 seqno = 4; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.seqno_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // repeated .PlayerState player_states = 8; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.player_states_), 0, 0, + (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + // repeated .UnknownMessage player_updates = 9; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.player_updates_), 0, 1, + (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvDefault)}, + // int64 tag11 = 11; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.tag11_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 tag17 = 17; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.tag17_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int32 num_msgs = 18; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.num_msgs_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 msgnum = 19; + {PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.msgnum_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + }}, {{ + {::_pbi::TcParser::GetTable<::PlayerState>()}, + {::_pbi::FieldAuxDefaultMessage{}, &::_UnknownMessage_default_instance_}, + }}, {{ + }}, +}; + +::uint8_t* ServerToClient::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:ServerToClient) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int32 tag1 = 1; + if (this->_internal_tag1() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this->_internal_tag1(), target); + } + + // int32 rider_id = 2; + if (this->_internal_rider_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this->_internal_rider_id(), target); + } + + // int64 world_time = 3; + if (this->_internal_world_time() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<3>( + stream, this->_internal_world_time(), target); + } + + // int32 seqno = 4; + if (this->_internal_seqno() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<4>( + stream, this->_internal_seqno(), target); + } + + // repeated .PlayerState player_states = 8; + for (unsigned i = 0, + n = static_cast(this->_internal_player_states_size()); i < n; i++) { + const auto& repfield = this->_internal_player_states().Get(i); + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessage(8, repfield, repfield.GetCachedSize(), target, stream); + } + + // repeated .UnknownMessage player_updates = 9; + for (unsigned i = 0, + n = static_cast(this->_internal_player_updates_size()); i < n; i++) { + const auto& repfield = this->_internal_player_updates().Get(i); + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessage(9, repfield, repfield.GetCachedSize(), target, stream); + } + + // int64 tag11 = 11; + if (this->_internal_tag11() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<11>( + stream, this->_internal_tag11(), target); + } + + // int64 tag17 = 17; + if (this->_internal_tag17() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray( + 17, this->_internal_tag17(), target); + } + + // int32 num_msgs = 18; + if (this->_internal_num_msgs() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 18, this->_internal_num_msgs(), target); + } + + // int32 msgnum = 19; + if (this->_internal_msgnum() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 19, this->_internal_msgnum(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:ServerToClient) + return target; +} + +::size_t ServerToClient::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:ServerToClient) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .PlayerState player_states = 8; + total_size += 1UL * this->_internal_player_states_size(); + for (const auto& msg : this->_internal_player_states()) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + // repeated .UnknownMessage player_updates = 9; + total_size += 1UL * this->_internal_player_updates_size(); + for (const auto& msg : this->_internal_player_updates()) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + // int32 tag1 = 1; + if (this->_internal_tag1() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_tag1()); + } + + // int32 rider_id = 2; + if (this->_internal_rider_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_rider_id()); + } + + // int64 world_time = 3; + if (this->_internal_world_time() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_world_time()); + } + + // int64 tag11 = 11; + if (this->_internal_tag11() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_tag11()); + } + + // int32 seqno = 4; + if (this->_internal_seqno() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_seqno()); + } + + // int32 num_msgs = 18; + if (this->_internal_num_msgs() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_num_msgs()); + } + + // int64 tag17 = 17; + if (this->_internal_tag17() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int64Size( + this->_internal_tag17()); + } + + // int32 msgnum = 19; + if (this->_internal_msgnum() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_msgnum()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData ServerToClient::_class_data_ = { + ServerToClient::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* ServerToClient::GetClassData() const { + return &_class_data_; +} + +void ServerToClient::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:ServerToClient) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_player_states()->MergeFrom( + from._internal_player_states()); + _this->_internal_mutable_player_updates()->MergeFrom( + from._internal_player_updates()); + if (from._internal_tag1() != 0) { + _this->_internal_set_tag1(from._internal_tag1()); + } + if (from._internal_rider_id() != 0) { + _this->_internal_set_rider_id(from._internal_rider_id()); + } + if (from._internal_world_time() != 0) { + _this->_internal_set_world_time(from._internal_world_time()); + } + if (from._internal_tag11() != 0) { + _this->_internal_set_tag11(from._internal_tag11()); + } + if (from._internal_seqno() != 0) { + _this->_internal_set_seqno(from._internal_seqno()); + } + if (from._internal_num_msgs() != 0) { + _this->_internal_set_num_msgs(from._internal_num_msgs()); + } + if (from._internal_tag17() != 0) { + _this->_internal_set_tag17(from._internal_tag17()); + } + if (from._internal_msgnum() != 0) { + _this->_internal_set_msgnum(from._internal_msgnum()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void ServerToClient::CopyFrom(const ServerToClient& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:ServerToClient) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool ServerToClient::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* ServerToClient::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void ServerToClient::InternalSwap(ServerToClient* PROTOBUF_RESTRICT other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.player_states_.InternalSwap(&other->_impl_.player_states_); + _impl_.player_updates_.InternalSwap(&other->_impl_.player_updates_); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.msgnum_) + + sizeof(ServerToClient::_impl_.msgnum_) + - PROTOBUF_FIELD_OFFSET(ServerToClient, _impl_.tag1_)>( + reinterpret_cast(&_impl_.tag1_), + reinterpret_cast(&other->_impl_.tag1_)); +} + +::google::protobuf::Metadata ServerToClient::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[6]); +} +// =================================================================== + +class WorldAttributes::_Internal { + public: +}; + +WorldAttributes::WorldAttributes(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:WorldAttributes) +} +inline PROTOBUF_NDEBUG_INLINE WorldAttributes::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : name_(arena, from.name_), + _cached_size_{0} {} + +WorldAttributes::WorldAttributes( + ::google::protobuf::Arena* arena, + const WorldAttributes& from) + : ::google::protobuf::Message(arena) { + WorldAttributes* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, tag3_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, tag3_), + offsetof(Impl_, world_id_) - + offsetof(Impl_, tag3_) + + sizeof(Impl_::world_id_)); + + // @@protoc_insertion_point(copy_constructor:WorldAttributes) +} +inline PROTOBUF_NDEBUG_INLINE WorldAttributes::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : name_(arena), + _cached_size_{0} {} + +inline void WorldAttributes::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, tag3_), + 0, + offsetof(Impl_, world_id_) - + offsetof(Impl_, tag3_) + + sizeof(Impl_::world_id_)); +} +WorldAttributes::~WorldAttributes() { + // @@protoc_insertion_point(destructor:WorldAttributes) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void WorldAttributes::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.name_.Destroy(); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void WorldAttributes::Clear() { +// @@protoc_insertion_point(message_clear_start:WorldAttributes) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.name_.ClearToEmpty(); + ::memset(&_impl_.tag3_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.world_id_) - + reinterpret_cast(&_impl_.tag3_)) + sizeof(_impl_.world_id_)); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* WorldAttributes::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<3, 6, 0, 28, 2> WorldAttributes::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 7, 56, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967184, // skipmap + offsetof(decltype(_table_), field_entries), + 6, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + &_WorldAttributes_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // int32 world_id = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(WorldAttributes, _impl_.world_id_), 63>(), + {8, 63, 0, PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.world_id_)}}, + // string name = 2; + {::_pbi::TcParser::FastUS1, + {18, 63, 0, PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.name_)}}, + // int64 tag3 = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(WorldAttributes, _impl_.tag3_), 63>(), + {24, 63, 0, PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.tag3_)}}, + // int64 tag5 = 4; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(WorldAttributes, _impl_.tag5_), 63>(), + {32, 63, 0, PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.tag5_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int64 world_time = 6; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(WorldAttributes, _impl_.world_time_), 63>(), + {48, 63, 0, PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.world_time_)}}, + // int64 clock_time = 7; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(WorldAttributes, _impl_.clock_time_), 63>(), + {56, 63, 0, PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.clock_time_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // int32 world_id = 1; + {PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.world_id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // string name = 2; + {PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.name_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // int64 tag3 = 3; + {PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.tag3_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 tag5 = 4; + {PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.tag5_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 world_time = 6; + {PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.world_time_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + // int64 clock_time = 7; + {PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.clock_time_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + }}, + // no aux_entries + {{ + "\17\0\4\0\0\0\0\0" + "WorldAttributes" + "name" + }}, +}; + +::uint8_t* WorldAttributes::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:WorldAttributes) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int32 world_id = 1; + if (this->_internal_world_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this->_internal_world_id(), target); + } + + // string name = 2; + if (!this->_internal_name().empty()) { + const std::string& _s = this->_internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "WorldAttributes.name"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // int64 tag3 = 3; + if (this->_internal_tag3() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<3>( + stream, this->_internal_tag3(), target); + } + + // int64 tag5 = 4; + if (this->_internal_tag5() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<4>( + stream, this->_internal_tag5(), target); + } + + // int64 world_time = 6; + if (this->_internal_world_time() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<6>( + stream, this->_internal_world_time(), target); + } + + // int64 clock_time = 7; + if (this->_internal_clock_time() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<7>( + stream, this->_internal_clock_time(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:WorldAttributes) + return target; +} + +::size_t WorldAttributes::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:WorldAttributes) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string name = 2; + if (!this->_internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // int64 tag3 = 3; + if (this->_internal_tag3() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_tag3()); + } + + // int64 tag5 = 4; + if (this->_internal_tag5() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_tag5()); + } + + // int64 world_time = 6; + if (this->_internal_world_time() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_world_time()); + } + + // int64 clock_time = 7; + if (this->_internal_clock_time() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_clock_time()); + } + + // int32 world_id = 1; + if (this->_internal_world_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_world_id()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData WorldAttributes::_class_data_ = { + WorldAttributes::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* WorldAttributes::GetClassData() const { + return &_class_data_; +} + +void WorldAttributes::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:WorldAttributes) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (from._internal_tag3() != 0) { + _this->_internal_set_tag3(from._internal_tag3()); + } + if (from._internal_tag5() != 0) { + _this->_internal_set_tag5(from._internal_tag5()); + } + if (from._internal_world_time() != 0) { + _this->_internal_set_world_time(from._internal_world_time()); + } + if (from._internal_clock_time() != 0) { + _this->_internal_set_clock_time(from._internal_clock_time()); + } + if (from._internal_world_id() != 0) { + _this->_internal_set_world_id(from._internal_world_id()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void WorldAttributes::CopyFrom(const WorldAttributes& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:WorldAttributes) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool WorldAttributes::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* WorldAttributes::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void WorldAttributes::InternalSwap(WorldAttributes* PROTOBUF_RESTRICT other) { + using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.world_id_) + + sizeof(WorldAttributes::_impl_.world_id_) + - PROTOBUF_FIELD_OFFSET(WorldAttributes, _impl_.tag3_)>( + reinterpret_cast(&_impl_.tag3_), + reinterpret_cast(&other->_impl_.tag3_)); +} + +::google::protobuf::Metadata WorldAttributes::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[7]); +} +// =================================================================== + +class WorldAttribute::_Internal { + public: +}; + +WorldAttribute::WorldAttribute(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:WorldAttribute) +} +WorldAttribute::WorldAttribute( + ::google::protobuf::Arena* arena, const WorldAttribute& from) + : WorldAttribute(arena) { + MergeFrom(from); +} +inline PROTOBUF_NDEBUG_INLINE WorldAttribute::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : _cached_size_{0} {} + +inline void WorldAttribute::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + _impl_.world_time_ = {}; +} +WorldAttribute::~WorldAttribute() { + // @@protoc_insertion_point(destructor:WorldAttribute) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void WorldAttribute::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void WorldAttribute::Clear() { +// @@protoc_insertion_point(message_clear_start:WorldAttribute) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.world_time_ = ::int64_t{0}; + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* WorldAttribute::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 0, 0, 2> WorldAttribute::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 2, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967293, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + &_WorldAttribute_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + // int64 world_time = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(WorldAttribute, _impl_.world_time_), 63>(), + {16, 63, 0, PROTOBUF_FIELD_OFFSET(WorldAttribute, _impl_.world_time_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // int64 world_time = 2; + {PROTOBUF_FIELD_OFFSET(WorldAttribute, _impl_.world_time_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt64)}, + }}, + // no aux_entries + {{ + }}, +}; + +::uint8_t* WorldAttribute::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:WorldAttribute) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int64 world_time = 2; + if (this->_internal_world_time() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt64ToArrayWithField<2>( + stream, this->_internal_world_time(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:WorldAttribute) + return target; +} + +::size_t WorldAttribute::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:WorldAttribute) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int64 world_time = 2; + if (this->_internal_world_time() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne( + this->_internal_world_time()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData WorldAttribute::_class_data_ = { + WorldAttribute::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* WorldAttribute::GetClassData() const { + return &_class_data_; +} + +void WorldAttribute::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:WorldAttribute) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_world_time() != 0) { + _this->_internal_set_world_time(from._internal_world_time()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void WorldAttribute::CopyFrom(const WorldAttribute& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:WorldAttribute) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool WorldAttribute::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* WorldAttribute::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void WorldAttribute::InternalSwap(WorldAttribute* PROTOBUF_RESTRICT other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_.world_time_, other->_impl_.world_time_); +} + +::google::protobuf::Metadata WorldAttribute::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[8]); +} +// =================================================================== + +class EventSubgroupProtobuf::_Internal { + public: +}; + +EventSubgroupProtobuf::EventSubgroupProtobuf(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:EventSubgroupProtobuf) +} +inline PROTOBUF_NDEBUG_INLINE EventSubgroupProtobuf::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : name_(arena, from.name_), + _cached_size_{0} {} + +EventSubgroupProtobuf::EventSubgroupProtobuf( + ::google::protobuf::Arena* arena, + const EventSubgroupProtobuf& from) + : ::google::protobuf::Message(arena) { + EventSubgroupProtobuf* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, id_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, id_), + offsetof(Impl_, jerseyhash_) - + offsetof(Impl_, id_) + + sizeof(Impl_::jerseyhash_)); + + // @@protoc_insertion_point(copy_constructor:EventSubgroupProtobuf) +} +inline PROTOBUF_NDEBUG_INLINE EventSubgroupProtobuf::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : name_(arena), + _cached_size_{0} {} + +inline void EventSubgroupProtobuf::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, id_), + 0, + offsetof(Impl_, jerseyhash_) - + offsetof(Impl_, id_) + + sizeof(Impl_::jerseyhash_)); +} +EventSubgroupProtobuf::~EventSubgroupProtobuf() { + // @@protoc_insertion_point(destructor:EventSubgroupProtobuf) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void EventSubgroupProtobuf::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.name_.Destroy(); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void EventSubgroupProtobuf::Clear() { +// @@protoc_insertion_point(message_clear_start:EventSubgroupProtobuf) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.name_.ClearToEmpty(); + ::memset(&_impl_.id_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.jerseyhash_) - + reinterpret_cast(&_impl_.id_)) + sizeof(_impl_.jerseyhash_)); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* EventSubgroupProtobuf::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<4, 9, 0, 42, 7> EventSubgroupProtobuf::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 36, 120, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 2397044604, // skipmap + offsetof(decltype(_table_), field_entries), + 9, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + &_EventSubgroupProtobuf_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // int32 id = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(EventSubgroupProtobuf, _impl_.id_), 63>(), + {8, 63, 0, PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.id_)}}, + // string name = 2; + {::_pbi::TcParser::FastUS1, + {18, 63, 0, PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.name_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 jerseyHash = 36; + {::_pbi::TcParser::FastV32S2, + {672, 63, 0, PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.jerseyhash_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 route = 22; + {::_pbi::TcParser::FastV32S2, + {432, 63, 0, PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.route_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 rules = 8; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(EventSubgroupProtobuf, _impl_.rules_), 63>(), + {64, 63, 0, PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.rules_)}}, + // int32 laps = 25; + {::_pbi::TcParser::FastV32S2, + {456, 63, 0, PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.laps_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 startLocation = 29; + {::_pbi::TcParser::FastV32S2, + {488, 63, 0, PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.startlocation_)}}, + // int32 label = 30; + {::_pbi::TcParser::FastV32S2, + {496, 63, 0, PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.label_)}}, + // int32 paceType = 31; + {::_pbi::TcParser::FastV32S2, + {504, 63, 0, PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.pacetype_)}}, + }}, {{ + 36, 0, 1, + 65534, 8, + 65535, 65535 + }}, {{ + // int32 id = 1; + {PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // string name = 2; + {PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.name_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // int32 rules = 8; + {PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.rules_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 route = 22; + {PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.route_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 laps = 25; + {PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.laps_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 startLocation = 29; + {PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.startlocation_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 label = 30; + {PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.label_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 paceType = 31; + {PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.pacetype_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 jerseyHash = 36; + {PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.jerseyhash_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + }}, + // no aux_entries + {{ + "\25\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0" + "EventSubgroupProtobuf" + "name" + }}, +}; + +::uint8_t* EventSubgroupProtobuf::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:EventSubgroupProtobuf) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int32 id = 1; + if (this->_internal_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this->_internal_id(), target); + } + + // string name = 2; + if (!this->_internal_name().empty()) { + const std::string& _s = this->_internal_name(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "EventSubgroupProtobuf.name"); + target = stream->WriteStringMaybeAliased(2, _s, target); + } + + // int32 rules = 8; + if (this->_internal_rules() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<8>( + stream, this->_internal_rules(), target); + } + + // int32 route = 22; + if (this->_internal_route() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 22, this->_internal_route(), target); + } + + // int32 laps = 25; + if (this->_internal_laps() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 25, this->_internal_laps(), target); + } + + // int32 startLocation = 29; + if (this->_internal_startlocation() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 29, this->_internal_startlocation(), target); + } + + // int32 label = 30; + if (this->_internal_label() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 30, this->_internal_label(), target); + } + + // int32 paceType = 31; + if (this->_internal_pacetype() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 31, this->_internal_pacetype(), target); + } + + // int32 jerseyHash = 36; + if (this->_internal_jerseyhash() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 36, this->_internal_jerseyhash(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:EventSubgroupProtobuf) + return target; +} + +::size_t EventSubgroupProtobuf::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:EventSubgroupProtobuf) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string name = 2; + if (!this->_internal_name().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // int32 id = 1; + if (this->_internal_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_id()); + } + + // int32 rules = 8; + if (this->_internal_rules() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_rules()); + } + + // int32 route = 22; + if (this->_internal_route() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_route()); + } + + // int32 laps = 25; + if (this->_internal_laps() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_laps()); + } + + // int32 startLocation = 29; + if (this->_internal_startlocation() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_startlocation()); + } + + // int32 label = 30; + if (this->_internal_label() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_label()); + } + + // int32 paceType = 31; + if (this->_internal_pacetype() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_pacetype()); + } + + // int32 jerseyHash = 36; + if (this->_internal_jerseyhash() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_jerseyhash()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData EventSubgroupProtobuf::_class_data_ = { + EventSubgroupProtobuf::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* EventSubgroupProtobuf::GetClassData() const { + return &_class_data_; +} + +void EventSubgroupProtobuf::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:EventSubgroupProtobuf) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_name().empty()) { + _this->_internal_set_name(from._internal_name()); + } + if (from._internal_id() != 0) { + _this->_internal_set_id(from._internal_id()); + } + if (from._internal_rules() != 0) { + _this->_internal_set_rules(from._internal_rules()); + } + if (from._internal_route() != 0) { + _this->_internal_set_route(from._internal_route()); + } + if (from._internal_laps() != 0) { + _this->_internal_set_laps(from._internal_laps()); + } + if (from._internal_startlocation() != 0) { + _this->_internal_set_startlocation(from._internal_startlocation()); + } + if (from._internal_label() != 0) { + _this->_internal_set_label(from._internal_label()); + } + if (from._internal_pacetype() != 0) { + _this->_internal_set_pacetype(from._internal_pacetype()); + } + if (from._internal_jerseyhash() != 0) { + _this->_internal_set_jerseyhash(from._internal_jerseyhash()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void EventSubgroupProtobuf::CopyFrom(const EventSubgroupProtobuf& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:EventSubgroupProtobuf) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool EventSubgroupProtobuf::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* EventSubgroupProtobuf::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void EventSubgroupProtobuf::InternalSwap(EventSubgroupProtobuf* PROTOBUF_RESTRICT other) { + using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, &other->_impl_.name_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.jerseyhash_) + + sizeof(EventSubgroupProtobuf::_impl_.jerseyhash_) + - PROTOBUF_FIELD_OFFSET(EventSubgroupProtobuf, _impl_.id_)>( + reinterpret_cast(&_impl_.id_), + reinterpret_cast(&other->_impl_.id_)); +} + +::google::protobuf::Metadata EventSubgroupProtobuf::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[9]); +} +// =================================================================== + +class RiderAttributes_AttributeMessage::_Internal { + public: +}; + +RiderAttributes_AttributeMessage::RiderAttributes_AttributeMessage(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:RiderAttributes.AttributeMessage) +} +inline PROTOBUF_NDEBUG_INLINE RiderAttributes_AttributeMessage::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : firstname_(arena, from.firstname_), + lastname_(arena, from.lastname_), + _cached_size_{0} {} + +RiderAttributes_AttributeMessage::RiderAttributes_AttributeMessage( + ::google::protobuf::Arena* arena, + const RiderAttributes_AttributeMessage& from) + : ::google::protobuf::Message(arena) { + RiderAttributes_AttributeMessage* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, myid_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, myid_), + offsetof(Impl_, countrycode_) - + offsetof(Impl_, myid_) + + sizeof(Impl_::countrycode_)); + + // @@protoc_insertion_point(copy_constructor:RiderAttributes.AttributeMessage) +} +inline PROTOBUF_NDEBUG_INLINE RiderAttributes_AttributeMessage::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : firstname_(arena), + lastname_(arena), + _cached_size_{0} {} + +inline void RiderAttributes_AttributeMessage::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, myid_), + 0, + offsetof(Impl_, countrycode_) - + offsetof(Impl_, myid_) + + sizeof(Impl_::countrycode_)); +} +RiderAttributes_AttributeMessage::~RiderAttributes_AttributeMessage() { + // @@protoc_insertion_point(destructor:RiderAttributes.AttributeMessage) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void RiderAttributes_AttributeMessage::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.firstname_.Destroy(); + _impl_.lastname_.Destroy(); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void RiderAttributes_AttributeMessage::Clear() { +// @@protoc_insertion_point(message_clear_start:RiderAttributes.AttributeMessage) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.firstname_.ClearToEmpty(); + _impl_.lastname_.ClearToEmpty(); + ::memset(&_impl_.myid_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.countrycode_) - + reinterpret_cast(&_impl_.myid_)) + sizeof(_impl_.countrycode_)); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* RiderAttributes_AttributeMessage::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<3, 5, 0, 58, 2> RiderAttributes_AttributeMessage::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 5, 56, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967264, // skipmap + offsetof(decltype(_table_), field_entries), + 5, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + &_RiderAttributes_AttributeMessage_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // int32 myId = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(RiderAttributes_AttributeMessage, _impl_.myid_), 63>(), + {8, 63, 0, PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.myid_)}}, + // int32 theirId = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(RiderAttributes_AttributeMessage, _impl_.theirid_), 63>(), + {16, 63, 0, PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.theirid_)}}, + // string firstName = 3; + {::_pbi::TcParser::FastUS1, + {26, 63, 0, PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.firstname_)}}, + // string lastName = 4; + {::_pbi::TcParser::FastUS1, + {34, 63, 0, PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.lastname_)}}, + // int32 countryCode = 5; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(RiderAttributes_AttributeMessage, _impl_.countrycode_), 63>(), + {40, 63, 0, PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.countrycode_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 65535, 65535 + }}, {{ + // int32 myId = 1; + {PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.myid_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 theirId = 2; + {PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.theirid_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // string firstName = 3; + {PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.firstname_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string lastName = 4; + {PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.lastname_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // int32 countryCode = 5; + {PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.countrycode_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + }}, + // no aux_entries + {{ + "\40\0\0\11\10\0\0\0" + "RiderAttributes.AttributeMessage" + "firstName" + "lastName" + }}, +}; + +::uint8_t* RiderAttributes_AttributeMessage::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:RiderAttributes.AttributeMessage) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int32 myId = 1; + if (this->_internal_myid() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this->_internal_myid(), target); + } + + // int32 theirId = 2; + if (this->_internal_theirid() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this->_internal_theirid(), target); + } + + // string firstName = 3; + if (!this->_internal_firstname().empty()) { + const std::string& _s = this->_internal_firstname(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "RiderAttributes.AttributeMessage.firstName"); + target = stream->WriteStringMaybeAliased(3, _s, target); + } + + // string lastName = 4; + if (!this->_internal_lastname().empty()) { + const std::string& _s = this->_internal_lastname(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "RiderAttributes.AttributeMessage.lastName"); + target = stream->WriteStringMaybeAliased(4, _s, target); + } + + // int32 countryCode = 5; + if (this->_internal_countrycode() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<5>( + stream, this->_internal_countrycode(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:RiderAttributes.AttributeMessage) + return target; +} + +::size_t RiderAttributes_AttributeMessage::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:RiderAttributes.AttributeMessage) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string firstName = 3; + if (!this->_internal_firstname().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_firstname()); + } + + // string lastName = 4; + if (!this->_internal_lastname().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_lastname()); + } + + // int32 myId = 1; + if (this->_internal_myid() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_myid()); + } + + // int32 theirId = 2; + if (this->_internal_theirid() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_theirid()); + } + + // int32 countryCode = 5; + if (this->_internal_countrycode() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_countrycode()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData RiderAttributes_AttributeMessage::_class_data_ = { + RiderAttributes_AttributeMessage::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* RiderAttributes_AttributeMessage::GetClassData() const { + return &_class_data_; +} + +void RiderAttributes_AttributeMessage::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:RiderAttributes.AttributeMessage) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_firstname().empty()) { + _this->_internal_set_firstname(from._internal_firstname()); + } + if (!from._internal_lastname().empty()) { + _this->_internal_set_lastname(from._internal_lastname()); + } + if (from._internal_myid() != 0) { + _this->_internal_set_myid(from._internal_myid()); + } + if (from._internal_theirid() != 0) { + _this->_internal_set_theirid(from._internal_theirid()); + } + if (from._internal_countrycode() != 0) { + _this->_internal_set_countrycode(from._internal_countrycode()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void RiderAttributes_AttributeMessage::CopyFrom(const RiderAttributes_AttributeMessage& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:RiderAttributes.AttributeMessage) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool RiderAttributes_AttributeMessage::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* RiderAttributes_AttributeMessage::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void RiderAttributes_AttributeMessage::InternalSwap(RiderAttributes_AttributeMessage* PROTOBUF_RESTRICT other) { + using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.firstname_, &other->_impl_.firstname_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.lastname_, &other->_impl_.lastname_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.countrycode_) + + sizeof(RiderAttributes_AttributeMessage::_impl_.countrycode_) + - PROTOBUF_FIELD_OFFSET(RiderAttributes_AttributeMessage, _impl_.myid_)>( + reinterpret_cast(&_impl_.myid_), + reinterpret_cast(&other->_impl_.myid_)); +} + +::google::protobuf::Metadata RiderAttributes_AttributeMessage::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[10]); +} +// =================================================================== + +class RiderAttributes::_Internal { + public: + using HasBits = decltype(std::declval()._impl_._has_bits_); + static constexpr ::int32_t kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_._has_bits_); + static const ::RiderAttributes_AttributeMessage& attributemessage(const RiderAttributes* msg); + static void set_has_attributemessage(HasBits* has_bits) { + (*has_bits)[0] |= 1u; + } +}; + +const ::RiderAttributes_AttributeMessage& RiderAttributes::_Internal::attributemessage(const RiderAttributes* msg) { + return *msg->_impl_.attributemessage_; +} +RiderAttributes::RiderAttributes(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:RiderAttributes) +} +inline PROTOBUF_NDEBUG_INLINE RiderAttributes::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : _has_bits_{from._has_bits_}, + _cached_size_{0} {} + +RiderAttributes::RiderAttributes( + ::google::protobuf::Arena* arena, + const RiderAttributes& from) + : ::google::protobuf::Message(arena) { + RiderAttributes* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::uint32_t cached_has_bits = _impl_._has_bits_[0]; + _impl_.attributemessage_ = (cached_has_bits & 0x00000001u) + ? CreateMaybeMessage<::RiderAttributes_AttributeMessage>(arena, *from._impl_.attributemessage_) + : nullptr; + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, f2_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, f2_), + offsetof(Impl_, f13_) - + offsetof(Impl_, f2_) + + sizeof(Impl_::f13_)); + + // @@protoc_insertion_point(copy_constructor:RiderAttributes) +} +inline PROTOBUF_NDEBUG_INLINE RiderAttributes::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : _cached_size_{0} {} + +inline void RiderAttributes::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, attributemessage_), + 0, + offsetof(Impl_, f13_) - + offsetof(Impl_, attributemessage_) + + sizeof(Impl_::f13_)); +} +RiderAttributes::~RiderAttributes() { + // @@protoc_insertion_point(destructor:RiderAttributes) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void RiderAttributes::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + delete _impl_.attributemessage_; + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void RiderAttributes::Clear() { +// @@protoc_insertion_point(message_clear_start:RiderAttributes) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + ABSL_DCHECK(_impl_.attributemessage_ != nullptr); + _impl_.attributemessage_->Clear(); + } + ::memset(&_impl_.f2_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.f13_) - + reinterpret_cast(&_impl_.f2_)) + sizeof(_impl_.f13_)); + _impl_._has_bits_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* RiderAttributes::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<2, 5, 1, 0, 2> RiderAttributes::_table_ = { + { + PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_._has_bits_), + 0, // no _extensions_ + 13, 24, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294962673, // skipmap + offsetof(decltype(_table_), field_entries), + 5, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + &_RiderAttributes_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + // .RiderAttributes.AttributeMessage attributeMessage = 4; + {::_pbi::TcParser::FastMtS1, + {34, 0, 0, PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.attributemessage_)}}, + // int32 f13 = 13; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(RiderAttributes, _impl_.f13_), 63>(), + {104, 63, 0, PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.f13_)}}, + // int32 f2 = 2; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(RiderAttributes, _impl_.f2_), 63>(), + {16, 63, 0, PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.f2_)}}, + // int32 f3 = 3; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(RiderAttributes, _impl_.f3_), 63>(), + {24, 63, 0, PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.f3_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // int32 f2 = 2; + {PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.f2_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 f3 = 3; + {PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.f3_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // .RiderAttributes.AttributeMessage attributeMessage = 4; + {PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.attributemessage_), _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kMessage | ::_fl::kTvTable)}, + // int32 theirId = 10; + {PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.theirid_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 f13 = 13; + {PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.f13_), -1, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + }}, {{ + {::_pbi::TcParser::GetTable<::RiderAttributes_AttributeMessage>()}, + }}, {{ + }}, +}; + +::uint8_t* RiderAttributes::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:RiderAttributes) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int32 f2 = 2; + if (this->_internal_f2() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<2>( + stream, this->_internal_f2(), target); + } + + // int32 f3 = 3; + if (this->_internal_f3() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<3>( + stream, this->_internal_f3(), target); + } + + cached_has_bits = _impl_._has_bits_[0]; + // .RiderAttributes.AttributeMessage attributeMessage = 4; + if (cached_has_bits & 0x00000001u) { + target = ::google::protobuf::internal::WireFormatLite::InternalWriteMessage( + 4, _Internal::attributemessage(this), + _Internal::attributemessage(this).GetCachedSize(), target, stream); + } + + // int32 theirId = 10; + if (this->_internal_theirid() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<10>( + stream, this->_internal_theirid(), target); + } + + // int32 f13 = 13; + if (this->_internal_f13() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<13>( + stream, this->_internal_f13(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:RiderAttributes) + return target; +} + +::size_t RiderAttributes::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:RiderAttributes) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // .RiderAttributes.AttributeMessage attributeMessage = 4; + cached_has_bits = _impl_._has_bits_[0]; + if (cached_has_bits & 0x00000001u) { + total_size += + 1 + ::google::protobuf::internal::WireFormatLite::MessageSize(*_impl_.attributemessage_); + } + + // int32 f2 = 2; + if (this->_internal_f2() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_f2()); + } + + // int32 f3 = 3; + if (this->_internal_f3() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_f3()); + } + + // int32 theirId = 10; + if (this->_internal_theirid() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_theirid()); + } + + // int32 f13 = 13; + if (this->_internal_f13() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_f13()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData RiderAttributes::_class_data_ = { + RiderAttributes::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* RiderAttributes::GetClassData() const { + return &_class_data_; +} + +void RiderAttributes::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:RiderAttributes) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) { + _this->_internal_mutable_attributemessage()->::RiderAttributes_AttributeMessage::MergeFrom( + from._internal_attributemessage()); + } + if (from._internal_f2() != 0) { + _this->_internal_set_f2(from._internal_f2()); + } + if (from._internal_f3() != 0) { + _this->_internal_set_f3(from._internal_f3()); + } + if (from._internal_theirid() != 0) { + _this->_internal_set_theirid(from._internal_theirid()); + } + if (from._internal_f13() != 0) { + _this->_internal_set_f13(from._internal_f13()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void RiderAttributes::CopyFrom(const RiderAttributes& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:RiderAttributes) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool RiderAttributes::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* RiderAttributes::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void RiderAttributes::InternalSwap(RiderAttributes* PROTOBUF_RESTRICT other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.f13_) + + sizeof(RiderAttributes::_impl_.f13_) + - PROTOBUF_FIELD_OFFSET(RiderAttributes, _impl_.attributemessage_)>( + reinterpret_cast(&_impl_.attributemessage_), + reinterpret_cast(&other->_impl_.attributemessage_)); +} + +::google::protobuf::Metadata RiderAttributes::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[11]); +} +// =================================================================== + +class Profiles::_Internal { + public: +}; + +Profiles::Profiles(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:Profiles) +} +inline PROTOBUF_NDEBUG_INLINE Profiles::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : profiles_{visibility, arena, from.profiles_}, + _cached_size_{0} {} + +Profiles::Profiles( + ::google::protobuf::Arena* arena, + const Profiles& from) + : ::google::protobuf::Message(arena) { + Profiles* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + + // @@protoc_insertion_point(copy_constructor:Profiles) +} +inline PROTOBUF_NDEBUG_INLINE Profiles::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : profiles_{visibility, arena}, + _cached_size_{0} {} + +inline void Profiles::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); +} +Profiles::~Profiles() { + // @@protoc_insertion_point(destructor:Profiles) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void Profiles::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void Profiles::Clear() { +// @@protoc_insertion_point(message_clear_start:Profiles) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.profiles_.Clear(); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* Profiles::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<0, 1, 1, 0, 2> Profiles::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 1, 0, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967294, // skipmap + offsetof(decltype(_table_), field_entries), + 1, // num_field_entries + 1, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + &_Profiles_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + // repeated .Profile profiles = 1; + {::_pbi::TcParser::FastMtR1, + {10, 63, 0, PROTOBUF_FIELD_OFFSET(Profiles, _impl_.profiles_)}}, + }}, {{ + 65535, 65535 + }}, {{ + // repeated .Profile profiles = 1; + {PROTOBUF_FIELD_OFFSET(Profiles, _impl_.profiles_), 0, 0, + (0 | ::_fl::kFcRepeated | ::_fl::kMessage | ::_fl::kTvTable)}, + }}, {{ + {::_pbi::TcParser::GetTable<::Profile>()}, + }}, {{ + }}, +}; + +::uint8_t* Profiles::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:Profiles) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // repeated .Profile profiles = 1; + for (unsigned i = 0, + n = static_cast(this->_internal_profiles_size()); i < n; i++) { + const auto& repfield = this->_internal_profiles().Get(i); + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessage(1, repfield, repfield.GetCachedSize(), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:Profiles) + return target; +} + +::size_t Profiles::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:Profiles) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .Profile profiles = 1; + total_size += 1UL * this->_internal_profiles_size(); + for (const auto& msg : this->_internal_profiles()) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSize(msg); + } + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData Profiles::_class_data_ = { + Profiles::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* Profiles::GetClassData() const { + return &_class_data_; +} + +void Profiles::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:Profiles) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + _this->_internal_mutable_profiles()->MergeFrom( + from._internal_profiles()); + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void Profiles::CopyFrom(const Profiles& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:Profiles) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool Profiles::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* Profiles::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void Profiles::InternalSwap(Profiles* PROTOBUF_RESTRICT other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + _impl_.profiles_.InternalSwap(&other->_impl_.profiles_); +} + +::google::protobuf::Metadata Profiles::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[12]); +} +// =================================================================== + +class Profile::_Internal { + public: +}; + +Profile::Profile(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(arena) { + SharedCtor(arena); + // @@protoc_insertion_point(arena_constructor:Profile) +} +inline PROTOBUF_NDEBUG_INLINE Profile::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, ::google::protobuf::Arena* arena, + const Impl_& from) + : firstname_(arena, from.firstname_), + lastname_(arena, from.lastname_), + launchedgameclient_(arena, from.launchedgameclient_), + _cached_size_{0} {} + +Profile::Profile( + ::google::protobuf::Arena* arena, + const Profile& from) + : ::google::protobuf::Message(arena) { + Profile* const _this = this; + (void)_this; + _internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>( + from._internal_metadata_); + new (&_impl_) Impl_(internal_visibility(), arena, from._impl_); + ::memcpy(reinterpret_cast(&_impl_) + + offsetof(Impl_, id_), + reinterpret_cast(&from._impl_) + + offsetof(Impl_, id_), + offsetof(Impl_, currentactivityid_) - + offsetof(Impl_, id_) + + sizeof(Impl_::currentactivityid_)); + + // @@protoc_insertion_point(copy_constructor:Profile) +} +inline PROTOBUF_NDEBUG_INLINE Profile::Impl_::Impl_( + ::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena) + : firstname_(arena), + lastname_(arena), + launchedgameclient_(arena), + _cached_size_{0} {} + +inline void Profile::SharedCtor(::_pb::Arena* arena) { + new (&_impl_) Impl_(internal_visibility(), arena); + ::memset(reinterpret_cast(&_impl_) + + offsetof(Impl_, id_), + 0, + offsetof(Impl_, currentactivityid_) - + offsetof(Impl_, id_) + + sizeof(Impl_::currentactivityid_)); +} +Profile::~Profile() { + // @@protoc_insertion_point(destructor:Profile) + _internal_metadata_.Delete<::google::protobuf::UnknownFieldSet>(); + SharedDtor(); +} +inline void Profile::SharedDtor() { + ABSL_DCHECK(GetArena() == nullptr); + _impl_.firstname_.Destroy(); + _impl_.lastname_.Destroy(); + _impl_.launchedgameclient_.Destroy(); + _impl_.~Impl_(); +} + +PROTOBUF_NOINLINE void Profile::Clear() { +// @@protoc_insertion_point(message_clear_start:Profile) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.firstname_.ClearToEmpty(); + _impl_.lastname_.ClearToEmpty(); + _impl_.launchedgameclient_.ClearToEmpty(); + ::memset(&_impl_.id_, 0, static_cast<::size_t>( + reinterpret_cast(&_impl_.currentactivityid_) - + reinterpret_cast(&_impl_.id_)) + sizeof(_impl_.currentactivityid_)); + _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); +} + +const char* Profile::_InternalParse( + const char* ptr, ::_pbi::ParseContext* ctx) { + ptr = ::_pbi::TcParser::ParseLoop(this, ptr, ctx, &_table_.header); + return ptr; +} + + +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 +const ::_pbi::TcParseTable<5, 18, 0, 67, 15> Profile::_table_ = { + { + 0, // no _has_bits_ + 0, // no _extensions_ + 109, 248, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294964934, // skipmap + offsetof(decltype(_table_), field_entries), + 18, // num_field_entries + 0, // num_aux_entries + offsetof(decltype(_table_), field_names), // no aux_entries + &_Profile_default_instance_._instance, + ::_pbi::TcParser::GenericFallback, // fallback + }, {{ + {::_pbi::TcParser::MiniParse, {}}, + // int32 id = 1; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Profile, _impl_.id_), 63>(), + {8, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.id_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // string firstName = 4; + {::_pbi::TcParser::FastUS1, + {34, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.firstname_)}}, + // string lastName = 5; + {::_pbi::TcParser::FastUS1, + {42, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.lastname_)}}, + // int32 male = 6; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Profile, _impl_.male_), 63>(), + {48, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.male_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 weight = 9; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Profile, _impl_.weight_), 63>(), + {72, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.weight_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 bodyType = 12; + {::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(Profile, _impl_.bodytype_), 63>(), + {96, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.bodytype_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 achievementLevel = 49; + {::_pbi::TcParser::FastV32S2, + {904, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.achievementlevel_)}}, + // int32 countryCode = 34; + {::_pbi::TcParser::FastV32S2, + {656, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.countrycode_)}}, + // int32 totalDistance = 35; + {::_pbi::TcParser::FastV32S2, + {664, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.totaldistance_)}}, + // int32 totalDistanceClimbed = 36; + {::_pbi::TcParser::FastV32S2, + {672, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.totaldistanceclimbed_)}}, + // int32 totalTimeInMinutes = 37; + {::_pbi::TcParser::FastV32S2, + {680, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.totaltimeinminutes_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 age = 55; + {::_pbi::TcParser::FastV32S2, + {952, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.age_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // int32 totalWattHours = 41; + {::_pbi::TcParser::FastV32S2, + {712, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.totalwatthours_)}}, + // int32 height = 42; + {::_pbi::TcParser::FastV32S2, + {720, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.height_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // string launchedGameClient = 108; + {::_pbi::TcParser::FastUS2, + {1762, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.launchedgameclient_)}}, + // int32 currentActivityId = 109; + {::_pbi::TcParser::FastV32S2, + {1768, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.currentactivityid_)}}, + // int32 totalExperiencePoints = 46; + {::_pbi::TcParser::FastV32S2, + {752, 63, 0, PROTOBUF_FIELD_OFFSET(Profile, _impl_.totalexperiencepoints_)}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, {{ + 34, 0, 5, + 28272, 6, 65499, 14, 65535, 16, 65535, 16, 62463, 16, + 65535, 65535 + }}, {{ + // int32 id = 1; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.id_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // string firstName = 4; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.firstname_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // string lastName = 5; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.lastname_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // int32 male = 6; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.male_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 weight = 9; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.weight_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 bodyType = 12; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.bodytype_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 countryCode = 34; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.countrycode_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 totalDistance = 35; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.totaldistance_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 totalDistanceClimbed = 36; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.totaldistanceclimbed_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 totalTimeInMinutes = 37; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.totaltimeinminutes_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 totalWattHours = 41; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.totalwatthours_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 height = 42; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.height_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 totalExperiencePoints = 46; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.totalexperiencepoints_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 achievementLevel = 49; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.achievementlevel_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 powerSource = 52; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.powersource_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // int32 age = 55; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.age_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + // string launchedGameClient = 108; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.launchedgameclient_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kUtf8String | ::_fl::kRepAString)}, + // int32 currentActivityId = 109; + {PROTOBUF_FIELD_OFFSET(Profile, _impl_.currentactivityid_), 0, 0, + (0 | ::_fl::kFcSingular | ::_fl::kInt32)}, + }}, + // no aux_entries + {{ + "\7\0\11\10\0\0\0\0\0\0\0\0\0\0\0\0\0\22\0\0\0\0\0\0" + "Profile" + "firstName" + "lastName" + "launchedGameClient" + }}, +}; + +::uint8_t* Profile::_InternalSerialize( + ::uint8_t* target, + ::google::protobuf::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:Profile) + ::uint32_t cached_has_bits = 0; + (void)cached_has_bits; + + // int32 id = 1; + if (this->_internal_id() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<1>( + stream, this->_internal_id(), target); + } + + // string firstName = 4; + if (!this->_internal_firstname().empty()) { + const std::string& _s = this->_internal_firstname(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "Profile.firstName"); + target = stream->WriteStringMaybeAliased(4, _s, target); + } + + // string lastName = 5; + if (!this->_internal_lastname().empty()) { + const std::string& _s = this->_internal_lastname(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "Profile.lastName"); + target = stream->WriteStringMaybeAliased(5, _s, target); + } + + // int32 male = 6; + if (this->_internal_male() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<6>( + stream, this->_internal_male(), target); + } + + // int32 weight = 9; + if (this->_internal_weight() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<9>( + stream, this->_internal_weight(), target); + } + + // int32 bodyType = 12; + if (this->_internal_bodytype() != 0) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArrayWithField<12>( + stream, this->_internal_bodytype(), target); + } + + // int32 countryCode = 34; + if (this->_internal_countrycode() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 34, this->_internal_countrycode(), target); + } + + // int32 totalDistance = 35; + if (this->_internal_totaldistance() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 35, this->_internal_totaldistance(), target); + } + + // int32 totalDistanceClimbed = 36; + if (this->_internal_totaldistanceclimbed() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 36, this->_internal_totaldistanceclimbed(), target); + } + + // int32 totalTimeInMinutes = 37; + if (this->_internal_totaltimeinminutes() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 37, this->_internal_totaltimeinminutes(), target); + } + + // int32 totalWattHours = 41; + if (this->_internal_totalwatthours() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 41, this->_internal_totalwatthours(), target); + } + + // int32 height = 42; + if (this->_internal_height() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 42, this->_internal_height(), target); + } + + // int32 totalExperiencePoints = 46; + if (this->_internal_totalexperiencepoints() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 46, this->_internal_totalexperiencepoints(), target); + } + + // int32 achievementLevel = 49; + if (this->_internal_achievementlevel() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 49, this->_internal_achievementlevel(), target); + } + + // int32 powerSource = 52; + if (this->_internal_powersource() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 52, this->_internal_powersource(), target); + } + + // int32 age = 55; + if (this->_internal_age() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 55, this->_internal_age(), target); + } + + // string launchedGameClient = 108; + if (!this->_internal_launchedgameclient().empty()) { + const std::string& _s = this->_internal_launchedgameclient(); + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + _s.data(), static_cast(_s.length()), ::google::protobuf::internal::WireFormatLite::SERIALIZE, "Profile.launchedGameClient"); + target = stream->WriteStringMaybeAliased(108, _s, target); + } + + // int32 currentActivityId = 109; + if (this->_internal_currentactivityid() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 109, this->_internal_currentactivityid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = + ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:Profile) + return target; +} + +::size_t Profile::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:Profile) + ::size_t total_size = 0; + + ::uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string firstName = 4; + if (!this->_internal_firstname().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_firstname()); + } + + // string lastName = 5; + if (!this->_internal_lastname().empty()) { + total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_lastname()); + } + + // string launchedGameClient = 108; + if (!this->_internal_launchedgameclient().empty()) { + total_size += 2 + ::google::protobuf::internal::WireFormatLite::StringSize( + this->_internal_launchedgameclient()); + } + + // int32 id = 1; + if (this->_internal_id() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_id()); + } + + // int32 male = 6; + if (this->_internal_male() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_male()); + } + + // int32 weight = 9; + if (this->_internal_weight() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_weight()); + } + + // int32 bodyType = 12; + if (this->_internal_bodytype() != 0) { + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_bodytype()); + } + + // int32 countryCode = 34; + if (this->_internal_countrycode() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_countrycode()); + } + + // int32 totalDistance = 35; + if (this->_internal_totaldistance() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_totaldistance()); + } + + // int32 totalDistanceClimbed = 36; + if (this->_internal_totaldistanceclimbed() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_totaldistanceclimbed()); + } + + // int32 totalTimeInMinutes = 37; + if (this->_internal_totaltimeinminutes() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_totaltimeinminutes()); + } + + // int32 totalWattHours = 41; + if (this->_internal_totalwatthours() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_totalwatthours()); + } + + // int32 height = 42; + if (this->_internal_height() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_height()); + } + + // int32 totalExperiencePoints = 46; + if (this->_internal_totalexperiencepoints() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_totalexperiencepoints()); + } + + // int32 achievementLevel = 49; + if (this->_internal_achievementlevel() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_achievementlevel()); + } + + // int32 powerSource = 52; + if (this->_internal_powersource() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_powersource()); + } + + // int32 age = 55; + if (this->_internal_age() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_age()); + } + + // int32 currentActivityId = 109; + if (this->_internal_currentactivityid() != 0) { + total_size += 2 + ::_pbi::WireFormatLite::Int32Size( + this->_internal_currentactivityid()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::google::protobuf::Message::ClassData Profile::_class_data_ = { + Profile::MergeImpl, + nullptr, // OnDemandRegisterArenaDtor +}; +const ::google::protobuf::Message::ClassData* Profile::GetClassData() const { + return &_class_data_; +} + +void Profile::MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:Profile) + ABSL_DCHECK_NE(&from, _this); + ::uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_firstname().empty()) { + _this->_internal_set_firstname(from._internal_firstname()); + } + if (!from._internal_lastname().empty()) { + _this->_internal_set_lastname(from._internal_lastname()); + } + if (!from._internal_launchedgameclient().empty()) { + _this->_internal_set_launchedgameclient(from._internal_launchedgameclient()); + } + if (from._internal_id() != 0) { + _this->_internal_set_id(from._internal_id()); + } + if (from._internal_male() != 0) { + _this->_internal_set_male(from._internal_male()); + } + if (from._internal_weight() != 0) { + _this->_internal_set_weight(from._internal_weight()); + } + if (from._internal_bodytype() != 0) { + _this->_internal_set_bodytype(from._internal_bodytype()); + } + if (from._internal_countrycode() != 0) { + _this->_internal_set_countrycode(from._internal_countrycode()); + } + if (from._internal_totaldistance() != 0) { + _this->_internal_set_totaldistance(from._internal_totaldistance()); + } + if (from._internal_totaldistanceclimbed() != 0) { + _this->_internal_set_totaldistanceclimbed(from._internal_totaldistanceclimbed()); + } + if (from._internal_totaltimeinminutes() != 0) { + _this->_internal_set_totaltimeinminutes(from._internal_totaltimeinminutes()); + } + if (from._internal_totalwatthours() != 0) { + _this->_internal_set_totalwatthours(from._internal_totalwatthours()); + } + if (from._internal_height() != 0) { + _this->_internal_set_height(from._internal_height()); + } + if (from._internal_totalexperiencepoints() != 0) { + _this->_internal_set_totalexperiencepoints(from._internal_totalexperiencepoints()); + } + if (from._internal_achievementlevel() != 0) { + _this->_internal_set_achievementlevel(from._internal_achievementlevel()); + } + if (from._internal_powersource() != 0) { + _this->_internal_set_powersource(from._internal_powersource()); + } + if (from._internal_age() != 0) { + _this->_internal_set_age(from._internal_age()); + } + if (from._internal_currentactivityid() != 0) { + _this->_internal_set_currentactivityid(from._internal_currentactivityid()); + } + _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); +} + +void Profile::CopyFrom(const Profile& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:Profile) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +PROTOBUF_NOINLINE bool Profile::IsInitialized() const { + return true; +} + +::_pbi::CachedSize* Profile::AccessCachedSize() const { + return &_impl_._cached_size_; +} +void Profile::InternalSwap(Profile* PROTOBUF_RESTRICT other) { + using std::swap; + auto* arena = GetArena(); + ABSL_DCHECK_EQ(arena, other->GetArena()); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.firstname_, &other->_impl_.firstname_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.lastname_, &other->_impl_.lastname_, arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.launchedgameclient_, &other->_impl_.launchedgameclient_, arena); + ::google::protobuf::internal::memswap< + PROTOBUF_FIELD_OFFSET(Profile, _impl_.currentactivityid_) + + sizeof(Profile::_impl_.currentactivityid_) + - PROTOBUF_FIELD_OFFSET(Profile, _impl_.id_)>( + reinterpret_cast(&_impl_.id_), + reinterpret_cast(&other->_impl_.id_)); +} + +::google::protobuf::Metadata Profile::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_zwift_5fmessages_2eproto_getter, &descriptor_table_zwift_5fmessages_2eproto_once, + file_level_metadata_zwift_5fmessages_2eproto[13]); +} +// @@protoc_insertion_point(namespace_scope) +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google +// @@protoc_insertion_point(global_scope) +#include "google/protobuf/port_undef.inc" diff --git a/src/zwift-api/zwift_messages.pb.h b/src/zwift-api/zwift_messages.pb.h new file mode 100644 index 000000000..aff883a9b --- /dev/null +++ b/src/zwift-api/zwift_messages.pb.h @@ -0,0 +1,6785 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: zwift_messages.proto +// Protobuf C++ Version: 4.25.1 + +#ifndef GOOGLE_PROTOBUF_INCLUDED_zwift_5fmessages_2eproto_2epb_2eh +#define GOOGLE_PROTOBUF_INCLUDED_zwift_5fmessages_2eproto_2epb_2eh + +#include +#include +#include +#include + +#include "google/protobuf/port_def.inc" +#if PROTOBUF_VERSION < 4025000 +#error "This file was generated by a newer version of protoc which is" +#error "incompatible with your Protocol Buffer headers. Please update" +#error "your headers." +#endif // PROTOBUF_VERSION + +#if 4025001 < PROTOBUF_MIN_PROTOC_VERSION +#error "This file was generated by an older version of protoc which is" +#error "incompatible with your Protocol Buffer headers. Please" +#error "regenerate this file with a newer version of protoc." +#endif // PROTOBUF_MIN_PROTOC_VERSION +#include "google/protobuf/port_undef.inc" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_bases.h" +#include "google/protobuf/generated_message_tctable_decl.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/unknown_field_set.h" +// @@protoc_insertion_point(includes) + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define PROTOBUF_INTERNAL_EXPORT_zwift_5fmessages_2eproto + +namespace google { +namespace protobuf { +namespace internal { +class AnyMetadata; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Internal implementation detail -- do not use these members. +struct TableStruct_zwift_5fmessages_2eproto { + static const ::uint32_t offsets[]; +}; +extern const ::google::protobuf::internal::DescriptorTable + descriptor_table_zwift_5fmessages_2eproto; +class ClientToServer; +struct ClientToServerDefaultTypeInternal; +extern ClientToServerDefaultTypeInternal _ClientToServer_default_instance_; +class EventSubgroupProtobuf; +struct EventSubgroupProtobufDefaultTypeInternal; +extern EventSubgroupProtobufDefaultTypeInternal _EventSubgroupProtobuf_default_instance_; +class PlayerState; +struct PlayerStateDefaultTypeInternal; +extern PlayerStateDefaultTypeInternal _PlayerState_default_instance_; +class Profile; +struct ProfileDefaultTypeInternal; +extern ProfileDefaultTypeInternal _Profile_default_instance_; +class Profiles; +struct ProfilesDefaultTypeInternal; +extern ProfilesDefaultTypeInternal _Profiles_default_instance_; +class RiderAttributes; +struct RiderAttributesDefaultTypeInternal; +extern RiderAttributesDefaultTypeInternal _RiderAttributes_default_instance_; +class RiderAttributes_AttributeMessage; +struct RiderAttributes_AttributeMessageDefaultTypeInternal; +extern RiderAttributes_AttributeMessageDefaultTypeInternal _RiderAttributes_AttributeMessage_default_instance_; +class SegmentResult; +struct SegmentResultDefaultTypeInternal; +extern SegmentResultDefaultTypeInternal _SegmentResult_default_instance_; +class SegmentResults; +struct SegmentResultsDefaultTypeInternal; +extern SegmentResultsDefaultTypeInternal _SegmentResults_default_instance_; +class ServerToClient; +struct ServerToClientDefaultTypeInternal; +extern ServerToClientDefaultTypeInternal _ServerToClient_default_instance_; +class UnknownMessage; +struct UnknownMessageDefaultTypeInternal; +extern UnknownMessageDefaultTypeInternal _UnknownMessage_default_instance_; +class UnknownMessage1; +struct UnknownMessage1DefaultTypeInternal; +extern UnknownMessage1DefaultTypeInternal _UnknownMessage1_default_instance_; +class WorldAttribute; +struct WorldAttributeDefaultTypeInternal; +extern WorldAttributeDefaultTypeInternal _WorldAttribute_default_instance_; +class WorldAttributes; +struct WorldAttributesDefaultTypeInternal; +extern WorldAttributesDefaultTypeInternal _WorldAttributes_default_instance_; +namespace google { +namespace protobuf { +} // namespace protobuf +} // namespace google + + +// =================================================================== + + +// ------------------------------------------------------------------- + +class WorldAttributes final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:WorldAttributes) */ { + public: + inline WorldAttributes() : WorldAttributes(nullptr) {} + ~WorldAttributes() override; + template + explicit PROTOBUF_CONSTEXPR WorldAttributes(::google::protobuf::internal::ConstantInitialized); + + inline WorldAttributes(const WorldAttributes& from) + : WorldAttributes(nullptr, from) {} + WorldAttributes(WorldAttributes&& from) noexcept + : WorldAttributes() { + *this = ::std::move(from); + } + + inline WorldAttributes& operator=(const WorldAttributes& from) { + CopyFrom(from); + return *this; + } + inline WorldAttributes& operator=(WorldAttributes&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const WorldAttributes& default_instance() { + return *internal_default_instance(); + } + static inline const WorldAttributes* internal_default_instance() { + return reinterpret_cast( + &_WorldAttributes_default_instance_); + } + static constexpr int kIndexInFileMessages = + 7; + + friend void swap(WorldAttributes& a, WorldAttributes& b) { + a.Swap(&b); + } + inline void Swap(WorldAttributes* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(WorldAttributes* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + WorldAttributes* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const WorldAttributes& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const WorldAttributes& from) { + WorldAttributes::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(WorldAttributes* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "WorldAttributes"; + } + protected: + explicit WorldAttributes(::google::protobuf::Arena* arena); + WorldAttributes(::google::protobuf::Arena* arena, const WorldAttributes& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 2, + kTag3FieldNumber = 3, + kTag5FieldNumber = 4, + kWorldTimeFieldNumber = 6, + kClockTimeFieldNumber = 7, + kWorldIdFieldNumber = 1, + }; + // string name = 2; + void clear_name() ; + const std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* value); + + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( + const std::string& value); + std::string* _internal_mutable_name(); + + public: + // int64 tag3 = 3; + void clear_tag3() ; + ::int64_t tag3() const; + void set_tag3(::int64_t value); + + private: + ::int64_t _internal_tag3() const; + void _internal_set_tag3(::int64_t value); + + public: + // int64 tag5 = 4; + void clear_tag5() ; + ::int64_t tag5() const; + void set_tag5(::int64_t value); + + private: + ::int64_t _internal_tag5() const; + void _internal_set_tag5(::int64_t value); + + public: + // int64 world_time = 6; + void clear_world_time() ; + ::int64_t world_time() const; + void set_world_time(::int64_t value); + + private: + ::int64_t _internal_world_time() const; + void _internal_set_world_time(::int64_t value); + + public: + // int64 clock_time = 7; + void clear_clock_time() ; + ::int64_t clock_time() const; + void set_clock_time(::int64_t value); + + private: + ::int64_t _internal_clock_time() const; + void _internal_set_clock_time(::int64_t value); + + public: + // int32 world_id = 1; + void clear_world_id() ; + ::int32_t world_id() const; + void set_world_id(::int32_t value); + + private: + ::int32_t _internal_world_id() const; + void _internal_set_world_id(::int32_t value); + + public: + // @@protoc_insertion_point(class_scope:WorldAttributes) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 3, 6, 0, + 28, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::ArenaStringPtr name_; + ::int64_t tag3_; + ::int64_t tag5_; + ::int64_t world_time_; + ::int64_t clock_time_; + ::int32_t world_id_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class WorldAttribute final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:WorldAttribute) */ { + public: + inline WorldAttribute() : WorldAttribute(nullptr) {} + ~WorldAttribute() override; + template + explicit PROTOBUF_CONSTEXPR WorldAttribute(::google::protobuf::internal::ConstantInitialized); + + inline WorldAttribute(const WorldAttribute& from) + : WorldAttribute(nullptr, from) {} + WorldAttribute(WorldAttribute&& from) noexcept + : WorldAttribute() { + *this = ::std::move(from); + } + + inline WorldAttribute& operator=(const WorldAttribute& from) { + CopyFrom(from); + return *this; + } + inline WorldAttribute& operator=(WorldAttribute&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const WorldAttribute& default_instance() { + return *internal_default_instance(); + } + static inline const WorldAttribute* internal_default_instance() { + return reinterpret_cast( + &_WorldAttribute_default_instance_); + } + static constexpr int kIndexInFileMessages = + 8; + + friend void swap(WorldAttribute& a, WorldAttribute& b) { + a.Swap(&b); + } + inline void Swap(WorldAttribute* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(WorldAttribute* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + WorldAttribute* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const WorldAttribute& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const WorldAttribute& from) { + WorldAttribute::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(WorldAttribute* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "WorldAttribute"; + } + protected: + explicit WorldAttribute(::google::protobuf::Arena* arena); + WorldAttribute(::google::protobuf::Arena* arena, const WorldAttribute& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kWorldTimeFieldNumber = 2, + }; + // int64 world_time = 2; + void clear_world_time() ; + ::int64_t world_time() const; + void set_world_time(::int64_t value); + + private: + ::int64_t _internal_world_time() const; + void _internal_set_world_time(::int64_t value); + + public: + // @@protoc_insertion_point(class_scope:WorldAttribute) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 0, 1, 0, + 0, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::int64_t world_time_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class UnknownMessage1 final : + public ::google::protobuf::internal::ZeroFieldsBase /* @@protoc_insertion_point(class_definition:UnknownMessage1) */ { + public: + inline UnknownMessage1() : UnknownMessage1(nullptr) {} + template + explicit PROTOBUF_CONSTEXPR UnknownMessage1(::google::protobuf::internal::ConstantInitialized); + + inline UnknownMessage1(const UnknownMessage1& from) + : UnknownMessage1(nullptr, from) {} + UnknownMessage1(UnknownMessage1&& from) noexcept + : UnknownMessage1() { + *this = ::std::move(from); + } + + inline UnknownMessage1& operator=(const UnknownMessage1& from) { + CopyFrom(from); + return *this; + } + inline UnknownMessage1& operator=(UnknownMessage1&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const UnknownMessage1& default_instance() { + return *internal_default_instance(); + } + static inline const UnknownMessage1* internal_default_instance() { + return reinterpret_cast( + &_UnknownMessage1_default_instance_); + } + static constexpr int kIndexInFileMessages = + 4; + + friend void swap(UnknownMessage1& a, UnknownMessage1& b) { + a.Swap(&b); + } + inline void Swap(UnknownMessage1* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UnknownMessage1* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + UnknownMessage1* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const UnknownMessage1& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const UnknownMessage1& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + public: + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "UnknownMessage1"; + } + protected: + explicit UnknownMessage1(::google::protobuf::Arena* arena); + UnknownMessage1(::google::protobuf::Arena* arena, const UnknownMessage1& from); + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // @@protoc_insertion_point(class_scope:UnknownMessage1) + private: + class _Internal; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + PROTOBUF_TSAN_DECLARE_MEMBER + }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class UnknownMessage final : + public ::google::protobuf::internal::ZeroFieldsBase /* @@protoc_insertion_point(class_definition:UnknownMessage) */ { + public: + inline UnknownMessage() : UnknownMessage(nullptr) {} + template + explicit PROTOBUF_CONSTEXPR UnknownMessage(::google::protobuf::internal::ConstantInitialized); + + inline UnknownMessage(const UnknownMessage& from) + : UnknownMessage(nullptr, from) {} + UnknownMessage(UnknownMessage&& from) noexcept + : UnknownMessage() { + *this = ::std::move(from); + } + + inline UnknownMessage& operator=(const UnknownMessage& from) { + CopyFrom(from); + return *this; + } + inline UnknownMessage& operator=(UnknownMessage&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const UnknownMessage& default_instance() { + return *internal_default_instance(); + } + static inline const UnknownMessage* internal_default_instance() { + return reinterpret_cast( + &_UnknownMessage_default_instance_); + } + static constexpr int kIndexInFileMessages = + 5; + + friend void swap(UnknownMessage& a, UnknownMessage& b) { + a.Swap(&b); + } + inline void Swap(UnknownMessage* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UnknownMessage* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + UnknownMessage* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::internal::ZeroFieldsBase::CopyFrom; + inline void CopyFrom(const UnknownMessage& from) { + ::google::protobuf::internal::ZeroFieldsBase::CopyImpl(*this, from); + } + using ::google::protobuf::internal::ZeroFieldsBase::MergeFrom; + void MergeFrom(const UnknownMessage& from) { + ::google::protobuf::internal::ZeroFieldsBase::MergeImpl(*this, from); + } + public: + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "UnknownMessage"; + } + protected: + explicit UnknownMessage(::google::protobuf::Arena* arena); + UnknownMessage(::google::protobuf::Arena* arena, const UnknownMessage& from); + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // @@protoc_insertion_point(class_scope:UnknownMessage) + private: + class _Internal; + + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + PROTOBUF_TSAN_DECLARE_MEMBER + }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class SegmentResult final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:SegmentResult) */ { + public: + inline SegmentResult() : SegmentResult(nullptr) {} + ~SegmentResult() override; + template + explicit PROTOBUF_CONSTEXPR SegmentResult(::google::protobuf::internal::ConstantInitialized); + + inline SegmentResult(const SegmentResult& from) + : SegmentResult(nullptr, from) {} + SegmentResult(SegmentResult&& from) noexcept + : SegmentResult() { + *this = ::std::move(from); + } + + inline SegmentResult& operator=(const SegmentResult& from) { + CopyFrom(from); + return *this; + } + inline SegmentResult& operator=(SegmentResult&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SegmentResult& default_instance() { + return *internal_default_instance(); + } + static inline const SegmentResult* internal_default_instance() { + return reinterpret_cast( + &_SegmentResult_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(SegmentResult& a, SegmentResult& b) { + a.Swap(&b); + } + inline void Swap(SegmentResult* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SegmentResult* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SegmentResult* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const SegmentResult& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const SegmentResult& from) { + SegmentResult::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(SegmentResult* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "SegmentResult"; + } + protected: + explicit SegmentResult(::google::protobuf::Arena* arena); + SegmentResult(::google::protobuf::Arena* arena, const SegmentResult& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFirstNameFieldNumber = 7, + kLastNameFieldNumber = 8, + kFinishTimeStrFieldNumber = 10, + kIdFieldNumber = 1, + kRiderIdFieldNumber = 2, + kEventSubgroupIdFieldNumber = 6, + kElapsedMsFieldNumber = 11, + kPowermeterFieldNumber = 12, + kWeightFieldNumber = 13, + kPowerFieldNumber = 15, + kHeartrateFieldNumber = 19, + }; + // string first_name = 7; + void clear_first_name() ; + const std::string& first_name() const; + template + void set_first_name(Arg_&& arg, Args_... args); + std::string* mutable_first_name(); + PROTOBUF_NODISCARD std::string* release_first_name(); + void set_allocated_first_name(std::string* value); + + private: + const std::string& _internal_first_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_first_name( + const std::string& value); + std::string* _internal_mutable_first_name(); + + public: + // string last_name = 8; + void clear_last_name() ; + const std::string& last_name() const; + template + void set_last_name(Arg_&& arg, Args_... args); + std::string* mutable_last_name(); + PROTOBUF_NODISCARD std::string* release_last_name(); + void set_allocated_last_name(std::string* value); + + private: + const std::string& _internal_last_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_last_name( + const std::string& value); + std::string* _internal_mutable_last_name(); + + public: + // string finish_time_str = 10; + void clear_finish_time_str() ; + const std::string& finish_time_str() const; + template + void set_finish_time_str(Arg_&& arg, Args_... args); + std::string* mutable_finish_time_str(); + PROTOBUF_NODISCARD std::string* release_finish_time_str(); + void set_allocated_finish_time_str(std::string* value); + + private: + const std::string& _internal_finish_time_str() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_finish_time_str( + const std::string& value); + std::string* _internal_mutable_finish_time_str(); + + public: + // int64 id = 1; + void clear_id() ; + ::int64_t id() const; + void set_id(::int64_t value); + + private: + ::int64_t _internal_id() const; + void _internal_set_id(::int64_t value); + + public: + // int64 rider_id = 2; + void clear_rider_id() ; + ::int64_t rider_id() const; + void set_rider_id(::int64_t value); + + private: + ::int64_t _internal_rider_id() const; + void _internal_set_rider_id(::int64_t value); + + public: + // int64 event_subgroup_id = 6; + void clear_event_subgroup_id() ; + ::int64_t event_subgroup_id() const; + void set_event_subgroup_id(::int64_t value); + + private: + ::int64_t _internal_event_subgroup_id() const; + void _internal_set_event_subgroup_id(::int64_t value); + + public: + // int64 elapsed_ms = 11; + void clear_elapsed_ms() ; + ::int64_t elapsed_ms() const; + void set_elapsed_ms(::int64_t value); + + private: + ::int64_t _internal_elapsed_ms() const; + void _internal_set_elapsed_ms(::int64_t value); + + public: + // int32 powermeter = 12; + void clear_powermeter() ; + ::int32_t powermeter() const; + void set_powermeter(::int32_t value); + + private: + ::int32_t _internal_powermeter() const; + void _internal_set_powermeter(::int32_t value); + + public: + // int32 weight = 13; + void clear_weight() ; + ::int32_t weight() const; + void set_weight(::int32_t value); + + private: + ::int32_t _internal_weight() const; + void _internal_set_weight(::int32_t value); + + public: + // int32 power = 15; + void clear_power() ; + ::int32_t power() const; + void set_power(::int32_t value); + + private: + ::int32_t _internal_power() const; + void _internal_set_power(::int32_t value); + + public: + // int32 heartrate = 19; + void clear_heartrate() ; + ::int32_t heartrate() const; + void set_heartrate(::int32_t value); + + private: + ::int32_t _internal_heartrate() const; + void _internal_set_heartrate(::int32_t value); + + public: + // @@protoc_insertion_point(class_scope:SegmentResult) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 4, 11, 0, + 64, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::ArenaStringPtr first_name_; + ::google::protobuf::internal::ArenaStringPtr last_name_; + ::google::protobuf::internal::ArenaStringPtr finish_time_str_; + ::int64_t id_; + ::int64_t rider_id_; + ::int64_t event_subgroup_id_; + ::int64_t elapsed_ms_; + ::int32_t powermeter_; + ::int32_t weight_; + ::int32_t power_; + ::int32_t heartrate_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class RiderAttributes_AttributeMessage final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:RiderAttributes.AttributeMessage) */ { + public: + inline RiderAttributes_AttributeMessage() : RiderAttributes_AttributeMessage(nullptr) {} + ~RiderAttributes_AttributeMessage() override; + template + explicit PROTOBUF_CONSTEXPR RiderAttributes_AttributeMessage(::google::protobuf::internal::ConstantInitialized); + + inline RiderAttributes_AttributeMessage(const RiderAttributes_AttributeMessage& from) + : RiderAttributes_AttributeMessage(nullptr, from) {} + RiderAttributes_AttributeMessage(RiderAttributes_AttributeMessage&& from) noexcept + : RiderAttributes_AttributeMessage() { + *this = ::std::move(from); + } + + inline RiderAttributes_AttributeMessage& operator=(const RiderAttributes_AttributeMessage& from) { + CopyFrom(from); + return *this; + } + inline RiderAttributes_AttributeMessage& operator=(RiderAttributes_AttributeMessage&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const RiderAttributes_AttributeMessage& default_instance() { + return *internal_default_instance(); + } + static inline const RiderAttributes_AttributeMessage* internal_default_instance() { + return reinterpret_cast( + &_RiderAttributes_AttributeMessage_default_instance_); + } + static constexpr int kIndexInFileMessages = + 10; + + friend void swap(RiderAttributes_AttributeMessage& a, RiderAttributes_AttributeMessage& b) { + a.Swap(&b); + } + inline void Swap(RiderAttributes_AttributeMessage* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(RiderAttributes_AttributeMessage* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + RiderAttributes_AttributeMessage* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const RiderAttributes_AttributeMessage& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const RiderAttributes_AttributeMessage& from) { + RiderAttributes_AttributeMessage::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(RiderAttributes_AttributeMessage* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "RiderAttributes.AttributeMessage"; + } + protected: + explicit RiderAttributes_AttributeMessage(::google::protobuf::Arena* arena); + RiderAttributes_AttributeMessage(::google::protobuf::Arena* arena, const RiderAttributes_AttributeMessage& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFirstNameFieldNumber = 3, + kLastNameFieldNumber = 4, + kMyIdFieldNumber = 1, + kTheirIdFieldNumber = 2, + kCountryCodeFieldNumber = 5, + }; + // string firstName = 3; + void clear_firstname() ; + const std::string& firstname() const; + template + void set_firstname(Arg_&& arg, Args_... args); + std::string* mutable_firstname(); + PROTOBUF_NODISCARD std::string* release_firstname(); + void set_allocated_firstname(std::string* value); + + private: + const std::string& _internal_firstname() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_firstname( + const std::string& value); + std::string* _internal_mutable_firstname(); + + public: + // string lastName = 4; + void clear_lastname() ; + const std::string& lastname() const; + template + void set_lastname(Arg_&& arg, Args_... args); + std::string* mutable_lastname(); + PROTOBUF_NODISCARD std::string* release_lastname(); + void set_allocated_lastname(std::string* value); + + private: + const std::string& _internal_lastname() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_lastname( + const std::string& value); + std::string* _internal_mutable_lastname(); + + public: + // int32 myId = 1; + void clear_myid() ; + ::int32_t myid() const; + void set_myid(::int32_t value); + + private: + ::int32_t _internal_myid() const; + void _internal_set_myid(::int32_t value); + + public: + // int32 theirId = 2; + void clear_theirid() ; + ::int32_t theirid() const; + void set_theirid(::int32_t value); + + private: + ::int32_t _internal_theirid() const; + void _internal_set_theirid(::int32_t value); + + public: + // int32 countryCode = 5; + void clear_countrycode() ; + ::int32_t countrycode() const; + void set_countrycode(::int32_t value); + + private: + ::int32_t _internal_countrycode() const; + void _internal_set_countrycode(::int32_t value); + + public: + // @@protoc_insertion_point(class_scope:RiderAttributes.AttributeMessage) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 3, 5, 0, + 58, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::ArenaStringPtr firstname_; + ::google::protobuf::internal::ArenaStringPtr lastname_; + ::int32_t myid_; + ::int32_t theirid_; + ::int32_t countrycode_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class Profile final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Profile) */ { + public: + inline Profile() : Profile(nullptr) {} + ~Profile() override; + template + explicit PROTOBUF_CONSTEXPR Profile(::google::protobuf::internal::ConstantInitialized); + + inline Profile(const Profile& from) + : Profile(nullptr, from) {} + Profile(Profile&& from) noexcept + : Profile() { + *this = ::std::move(from); + } + + inline Profile& operator=(const Profile& from) { + CopyFrom(from); + return *this; + } + inline Profile& operator=(Profile&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Profile& default_instance() { + return *internal_default_instance(); + } + static inline const Profile* internal_default_instance() { + return reinterpret_cast( + &_Profile_default_instance_); + } + static constexpr int kIndexInFileMessages = + 13; + + friend void swap(Profile& a, Profile& b) { + a.Swap(&b); + } + inline void Swap(Profile* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Profile* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Profile* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const Profile& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const Profile& from) { + Profile::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(Profile* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "Profile"; + } + protected: + explicit Profile(::google::protobuf::Arena* arena); + Profile(::google::protobuf::Arena* arena, const Profile& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFirstNameFieldNumber = 4, + kLastNameFieldNumber = 5, + kLaunchedGameClientFieldNumber = 108, + kIdFieldNumber = 1, + kMaleFieldNumber = 6, + kWeightFieldNumber = 9, + kBodyTypeFieldNumber = 12, + kCountryCodeFieldNumber = 34, + kTotalDistanceFieldNumber = 35, + kTotalDistanceClimbedFieldNumber = 36, + kTotalTimeInMinutesFieldNumber = 37, + kTotalWattHoursFieldNumber = 41, + kHeightFieldNumber = 42, + kTotalExperiencePointsFieldNumber = 46, + kAchievementLevelFieldNumber = 49, + kPowerSourceFieldNumber = 52, + kAgeFieldNumber = 55, + kCurrentActivityIdFieldNumber = 109, + }; + // string firstName = 4; + void clear_firstname() ; + const std::string& firstname() const; + template + void set_firstname(Arg_&& arg, Args_... args); + std::string* mutable_firstname(); + PROTOBUF_NODISCARD std::string* release_firstname(); + void set_allocated_firstname(std::string* value); + + private: + const std::string& _internal_firstname() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_firstname( + const std::string& value); + std::string* _internal_mutable_firstname(); + + public: + // string lastName = 5; + void clear_lastname() ; + const std::string& lastname() const; + template + void set_lastname(Arg_&& arg, Args_... args); + std::string* mutable_lastname(); + PROTOBUF_NODISCARD std::string* release_lastname(); + void set_allocated_lastname(std::string* value); + + private: + const std::string& _internal_lastname() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_lastname( + const std::string& value); + std::string* _internal_mutable_lastname(); + + public: + // string launchedGameClient = 108; + void clear_launchedgameclient() ; + const std::string& launchedgameclient() const; + template + void set_launchedgameclient(Arg_&& arg, Args_... args); + std::string* mutable_launchedgameclient(); + PROTOBUF_NODISCARD std::string* release_launchedgameclient(); + void set_allocated_launchedgameclient(std::string* value); + + private: + const std::string& _internal_launchedgameclient() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_launchedgameclient( + const std::string& value); + std::string* _internal_mutable_launchedgameclient(); + + public: + // int32 id = 1; + void clear_id() ; + ::int32_t id() const; + void set_id(::int32_t value); + + private: + ::int32_t _internal_id() const; + void _internal_set_id(::int32_t value); + + public: + // int32 male = 6; + void clear_male() ; + ::int32_t male() const; + void set_male(::int32_t value); + + private: + ::int32_t _internal_male() const; + void _internal_set_male(::int32_t value); + + public: + // int32 weight = 9; + void clear_weight() ; + ::int32_t weight() const; + void set_weight(::int32_t value); + + private: + ::int32_t _internal_weight() const; + void _internal_set_weight(::int32_t value); + + public: + // int32 bodyType = 12; + void clear_bodytype() ; + ::int32_t bodytype() const; + void set_bodytype(::int32_t value); + + private: + ::int32_t _internal_bodytype() const; + void _internal_set_bodytype(::int32_t value); + + public: + // int32 countryCode = 34; + void clear_countrycode() ; + ::int32_t countrycode() const; + void set_countrycode(::int32_t value); + + private: + ::int32_t _internal_countrycode() const; + void _internal_set_countrycode(::int32_t value); + + public: + // int32 totalDistance = 35; + void clear_totaldistance() ; + ::int32_t totaldistance() const; + void set_totaldistance(::int32_t value); + + private: + ::int32_t _internal_totaldistance() const; + void _internal_set_totaldistance(::int32_t value); + + public: + // int32 totalDistanceClimbed = 36; + void clear_totaldistanceclimbed() ; + ::int32_t totaldistanceclimbed() const; + void set_totaldistanceclimbed(::int32_t value); + + private: + ::int32_t _internal_totaldistanceclimbed() const; + void _internal_set_totaldistanceclimbed(::int32_t value); + + public: + // int32 totalTimeInMinutes = 37; + void clear_totaltimeinminutes() ; + ::int32_t totaltimeinminutes() const; + void set_totaltimeinminutes(::int32_t value); + + private: + ::int32_t _internal_totaltimeinminutes() const; + void _internal_set_totaltimeinminutes(::int32_t value); + + public: + // int32 totalWattHours = 41; + void clear_totalwatthours() ; + ::int32_t totalwatthours() const; + void set_totalwatthours(::int32_t value); + + private: + ::int32_t _internal_totalwatthours() const; + void _internal_set_totalwatthours(::int32_t value); + + public: + // int32 height = 42; + void clear_height() ; + ::int32_t height() const; + void set_height(::int32_t value); + + private: + ::int32_t _internal_height() const; + void _internal_set_height(::int32_t value); + + public: + // int32 totalExperiencePoints = 46; + void clear_totalexperiencepoints() ; + ::int32_t totalexperiencepoints() const; + void set_totalexperiencepoints(::int32_t value); + + private: + ::int32_t _internal_totalexperiencepoints() const; + void _internal_set_totalexperiencepoints(::int32_t value); + + public: + // int32 achievementLevel = 49; + void clear_achievementlevel() ; + ::int32_t achievementlevel() const; + void set_achievementlevel(::int32_t value); + + private: + ::int32_t _internal_achievementlevel() const; + void _internal_set_achievementlevel(::int32_t value); + + public: + // int32 powerSource = 52; + void clear_powersource() ; + ::int32_t powersource() const; + void set_powersource(::int32_t value); + + private: + ::int32_t _internal_powersource() const; + void _internal_set_powersource(::int32_t value); + + public: + // int32 age = 55; + void clear_age() ; + ::int32_t age() const; + void set_age(::int32_t value); + + private: + ::int32_t _internal_age() const; + void _internal_set_age(::int32_t value); + + public: + // int32 currentActivityId = 109; + void clear_currentactivityid() ; + ::int32_t currentactivityid() const; + void set_currentactivityid(::int32_t value); + + private: + ::int32_t _internal_currentactivityid() const; + void _internal_set_currentactivityid(::int32_t value); + + public: + // @@protoc_insertion_point(class_scope:Profile) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 5, 18, 0, + 67, 15> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::ArenaStringPtr firstname_; + ::google::protobuf::internal::ArenaStringPtr lastname_; + ::google::protobuf::internal::ArenaStringPtr launchedgameclient_; + ::int32_t id_; + ::int32_t male_; + ::int32_t weight_; + ::int32_t bodytype_; + ::int32_t countrycode_; + ::int32_t totaldistance_; + ::int32_t totaldistanceclimbed_; + ::int32_t totaltimeinminutes_; + ::int32_t totalwatthours_; + ::int32_t height_; + ::int32_t totalexperiencepoints_; + ::int32_t achievementlevel_; + ::int32_t powersource_; + ::int32_t age_; + ::int32_t currentactivityid_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class PlayerState final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:PlayerState) */ { + public: + inline PlayerState() : PlayerState(nullptr) {} + ~PlayerState() override; + template + explicit PROTOBUF_CONSTEXPR PlayerState(::google::protobuf::internal::ConstantInitialized); + + inline PlayerState(const PlayerState& from) + : PlayerState(nullptr, from) {} + PlayerState(PlayerState&& from) noexcept + : PlayerState() { + *this = ::std::move(from); + } + + inline PlayerState& operator=(const PlayerState& from) { + CopyFrom(from); + return *this; + } + inline PlayerState& operator=(PlayerState&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const PlayerState& default_instance() { + return *internal_default_instance(); + } + static inline const PlayerState* internal_default_instance() { + return reinterpret_cast( + &_PlayerState_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(PlayerState& a, PlayerState& b) { + a.Swap(&b); + } + inline void Swap(PlayerState* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(PlayerState* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + PlayerState* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const PlayerState& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const PlayerState& from) { + PlayerState::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(PlayerState* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "PlayerState"; + } + protected: + explicit PlayerState(::google::protobuf::Arena* arena); + PlayerState(::google::protobuf::Arena* arena, const PlayerState& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kWorldTimeFieldNumber = 2, + kIdFieldNumber = 1, + kDistanceFieldNumber = 3, + kRoadTimeFieldNumber = 4, + kLapsFieldNumber = 5, + kSpeedFieldNumber = 6, + kRoadPositionFieldNumber = 8, + kCadenceUHzFieldNumber = 9, + kHeartrateFieldNumber = 11, + kHeadingFieldNumber = 13, + kPowerFieldNumber = 12, + kLeanFieldNumber = 14, + kClimbingFieldNumber = 15, + kTimeFieldNumber = 16, + kF19FieldNumber = 19, + kF20FieldNumber = 20, + kCustomisationIdFieldNumber = 22, + kProgressFieldNumber = 21, + kJustWatchingFieldNumber = 23, + kCaloriesFieldNumber = 24, + kXFieldNumber = 25, + kAltitudeFieldNumber = 26, + kYFieldNumber = 27, + kWatchingRiderIdFieldNumber = 28, + kGroupIdFieldNumber = 29, + kSportFieldNumber = 31, + }; + // int64 worldTime = 2; + void clear_worldtime() ; + ::int64_t worldtime() const; + void set_worldtime(::int64_t value); + + private: + ::int64_t _internal_worldtime() const; + void _internal_set_worldtime(::int64_t value); + + public: + // int32 id = 1; + void clear_id() ; + ::int32_t id() const; + void set_id(::int32_t value); + + private: + ::int32_t _internal_id() const; + void _internal_set_id(::int32_t value); + + public: + // int32 distance = 3; + void clear_distance() ; + ::int32_t distance() const; + void set_distance(::int32_t value); + + private: + ::int32_t _internal_distance() const; + void _internal_set_distance(::int32_t value); + + public: + // int32 roadTime = 4; + void clear_roadtime() ; + ::int32_t roadtime() const; + void set_roadtime(::int32_t value); + + private: + ::int32_t _internal_roadtime() const; + void _internal_set_roadtime(::int32_t value); + + public: + // int32 laps = 5; + void clear_laps() ; + ::int32_t laps() const; + void set_laps(::int32_t value); + + private: + ::int32_t _internal_laps() const; + void _internal_set_laps(::int32_t value); + + public: + // int32 speed = 6; + void clear_speed() ; + ::int32_t speed() const; + void set_speed(::int32_t value); + + private: + ::int32_t _internal_speed() const; + void _internal_set_speed(::int32_t value); + + public: + // int32 roadPosition = 8; + void clear_roadposition() ; + ::int32_t roadposition() const; + void set_roadposition(::int32_t value); + + private: + ::int32_t _internal_roadposition() const; + void _internal_set_roadposition(::int32_t value); + + public: + // int32 cadenceUHz = 9; + void clear_cadenceuhz() ; + ::int32_t cadenceuhz() const; + void set_cadenceuhz(::int32_t value); + + private: + ::int32_t _internal_cadenceuhz() const; + void _internal_set_cadenceuhz(::int32_t value); + + public: + // int32 heartrate = 11; + void clear_heartrate() ; + ::int32_t heartrate() const; + void set_heartrate(::int32_t value); + + private: + ::int32_t _internal_heartrate() const; + void _internal_set_heartrate(::int32_t value); + + public: + // int64 heading = 13; + void clear_heading() ; + ::int64_t heading() const; + void set_heading(::int64_t value); + + private: + ::int64_t _internal_heading() const; + void _internal_set_heading(::int64_t value); + + public: + // int32 power = 12; + void clear_power() ; + ::int32_t power() const; + void set_power(::int32_t value); + + private: + ::int32_t _internal_power() const; + void _internal_set_power(::int32_t value); + + public: + // int32 lean = 14; + void clear_lean() ; + ::int32_t lean() const; + void set_lean(::int32_t value); + + private: + ::int32_t _internal_lean() const; + void _internal_set_lean(::int32_t value); + + public: + // int32 climbing = 15; + void clear_climbing() ; + ::int32_t climbing() const; + void set_climbing(::int32_t value); + + private: + ::int32_t _internal_climbing() const; + void _internal_set_climbing(::int32_t value); + + public: + // int32 time = 16; + void clear_time() ; + ::int32_t time() const; + void set_time(::int32_t value); + + private: + ::int32_t _internal_time() const; + void _internal_set_time(::int32_t value); + + public: + // int32 f19 = 19; + void clear_f19() ; + ::int32_t f19() const; + void set_f19(::int32_t value); + + private: + ::int32_t _internal_f19() const; + void _internal_set_f19(::int32_t value); + + public: + // int32 f20 = 20; + void clear_f20() ; + ::int32_t f20() const; + void set_f20(::int32_t value); + + private: + ::int32_t _internal_f20() const; + void _internal_set_f20(::int32_t value); + + public: + // int64 customisationId = 22; + void clear_customisationid() ; + ::int64_t customisationid() const; + void set_customisationid(::int64_t value); + + private: + ::int64_t _internal_customisationid() const; + void _internal_set_customisationid(::int64_t value); + + public: + // int32 progress = 21; + void clear_progress() ; + ::int32_t progress() const; + void set_progress(::int32_t value); + + private: + ::int32_t _internal_progress() const; + void _internal_set_progress(::int32_t value); + + public: + // int32 justWatching = 23; + void clear_justwatching() ; + ::int32_t justwatching() const; + void set_justwatching(::int32_t value); + + private: + ::int32_t _internal_justwatching() const; + void _internal_set_justwatching(::int32_t value); + + public: + // int32 calories = 24; + void clear_calories() ; + ::int32_t calories() const; + void set_calories(::int32_t value); + + private: + ::int32_t _internal_calories() const; + void _internal_set_calories(::int32_t value); + + public: + // float x = 25; + void clear_x() ; + float x() const; + void set_x(float value); + + private: + float _internal_x() const; + void _internal_set_x(float value); + + public: + // float altitude = 26; + void clear_altitude() ; + float altitude() const; + void set_altitude(float value); + + private: + float _internal_altitude() const; + void _internal_set_altitude(float value); + + public: + // float y = 27; + void clear_y() ; + float y() const; + void set_y(float value); + + private: + float _internal_y() const; + void _internal_set_y(float value); + + public: + // int32 watchingRiderId = 28; + void clear_watchingriderid() ; + ::int32_t watchingriderid() const; + void set_watchingriderid(::int32_t value); + + private: + ::int32_t _internal_watchingriderid() const; + void _internal_set_watchingriderid(::int32_t value); + + public: + // int32 groupId = 29; + void clear_groupid() ; + ::int32_t groupid() const; + void set_groupid(::int32_t value); + + private: + ::int32_t _internal_groupid() const; + void _internal_set_groupid(::int32_t value); + + public: + // int64 sport = 31; + void clear_sport() ; + ::int64_t sport() const; + void set_sport(::int64_t value); + + private: + ::int64_t _internal_sport() const; + void _internal_set_sport(::int64_t value); + + public: + // @@protoc_insertion_point(class_scope:PlayerState) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 5, 26, 0, + 0, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::int64_t worldtime_; + ::int32_t id_; + ::int32_t distance_; + ::int32_t roadtime_; + ::int32_t laps_; + ::int32_t speed_; + ::int32_t roadposition_; + ::int32_t cadenceuhz_; + ::int32_t heartrate_; + ::int64_t heading_; + ::int32_t power_; + ::int32_t lean_; + ::int32_t climbing_; + ::int32_t time_; + ::int32_t f19_; + ::int32_t f20_; + ::int64_t customisationid_; + ::int32_t progress_; + ::int32_t justwatching_; + ::int32_t calories_; + float x_; + float altitude_; + float y_; + ::int32_t watchingriderid_; + ::int32_t groupid_; + ::int64_t sport_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class EventSubgroupProtobuf final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:EventSubgroupProtobuf) */ { + public: + inline EventSubgroupProtobuf() : EventSubgroupProtobuf(nullptr) {} + ~EventSubgroupProtobuf() override; + template + explicit PROTOBUF_CONSTEXPR EventSubgroupProtobuf(::google::protobuf::internal::ConstantInitialized); + + inline EventSubgroupProtobuf(const EventSubgroupProtobuf& from) + : EventSubgroupProtobuf(nullptr, from) {} + EventSubgroupProtobuf(EventSubgroupProtobuf&& from) noexcept + : EventSubgroupProtobuf() { + *this = ::std::move(from); + } + + inline EventSubgroupProtobuf& operator=(const EventSubgroupProtobuf& from) { + CopyFrom(from); + return *this; + } + inline EventSubgroupProtobuf& operator=(EventSubgroupProtobuf&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const EventSubgroupProtobuf& default_instance() { + return *internal_default_instance(); + } + static inline const EventSubgroupProtobuf* internal_default_instance() { + return reinterpret_cast( + &_EventSubgroupProtobuf_default_instance_); + } + static constexpr int kIndexInFileMessages = + 9; + + friend void swap(EventSubgroupProtobuf& a, EventSubgroupProtobuf& b) { + a.Swap(&b); + } + inline void Swap(EventSubgroupProtobuf* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(EventSubgroupProtobuf* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + EventSubgroupProtobuf* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const EventSubgroupProtobuf& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const EventSubgroupProtobuf& from) { + EventSubgroupProtobuf::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(EventSubgroupProtobuf* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "EventSubgroupProtobuf"; + } + protected: + explicit EventSubgroupProtobuf(::google::protobuf::Arena* arena); + EventSubgroupProtobuf(::google::protobuf::Arena* arena, const EventSubgroupProtobuf& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 2, + kIdFieldNumber = 1, + kRulesFieldNumber = 8, + kRouteFieldNumber = 22, + kLapsFieldNumber = 25, + kStartLocationFieldNumber = 29, + kLabelFieldNumber = 30, + kPaceTypeFieldNumber = 31, + kJerseyHashFieldNumber = 36, + }; + // string name = 2; + void clear_name() ; + const std::string& name() const; + template + void set_name(Arg_&& arg, Args_... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* value); + + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( + const std::string& value); + std::string* _internal_mutable_name(); + + public: + // int32 id = 1; + void clear_id() ; + ::int32_t id() const; + void set_id(::int32_t value); + + private: + ::int32_t _internal_id() const; + void _internal_set_id(::int32_t value); + + public: + // int32 rules = 8; + void clear_rules() ; + ::int32_t rules() const; + void set_rules(::int32_t value); + + private: + ::int32_t _internal_rules() const; + void _internal_set_rules(::int32_t value); + + public: + // int32 route = 22; + void clear_route() ; + ::int32_t route() const; + void set_route(::int32_t value); + + private: + ::int32_t _internal_route() const; + void _internal_set_route(::int32_t value); + + public: + // int32 laps = 25; + void clear_laps() ; + ::int32_t laps() const; + void set_laps(::int32_t value); + + private: + ::int32_t _internal_laps() const; + void _internal_set_laps(::int32_t value); + + public: + // int32 startLocation = 29; + void clear_startlocation() ; + ::int32_t startlocation() const; + void set_startlocation(::int32_t value); + + private: + ::int32_t _internal_startlocation() const; + void _internal_set_startlocation(::int32_t value); + + public: + // int32 label = 30; + void clear_label() ; + ::int32_t label() const; + void set_label(::int32_t value); + + private: + ::int32_t _internal_label() const; + void _internal_set_label(::int32_t value); + + public: + // int32 paceType = 31; + void clear_pacetype() ; + ::int32_t pacetype() const; + void set_pacetype(::int32_t value); + + private: + ::int32_t _internal_pacetype() const; + void _internal_set_pacetype(::int32_t value); + + public: + // int32 jerseyHash = 36; + void clear_jerseyhash() ; + ::int32_t jerseyhash() const; + void set_jerseyhash(::int32_t value); + + private: + ::int32_t _internal_jerseyhash() const; + void _internal_set_jerseyhash(::int32_t value); + + public: + // @@protoc_insertion_point(class_scope:EventSubgroupProtobuf) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 4, 9, 0, + 42, 7> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::ArenaStringPtr name_; + ::int32_t id_; + ::int32_t rules_; + ::int32_t route_; + ::int32_t laps_; + ::int32_t startlocation_; + ::int32_t label_; + ::int32_t pacetype_; + ::int32_t jerseyhash_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class ServerToClient final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:ServerToClient) */ { + public: + inline ServerToClient() : ServerToClient(nullptr) {} + ~ServerToClient() override; + template + explicit PROTOBUF_CONSTEXPR ServerToClient(::google::protobuf::internal::ConstantInitialized); + + inline ServerToClient(const ServerToClient& from) + : ServerToClient(nullptr, from) {} + ServerToClient(ServerToClient&& from) noexcept + : ServerToClient() { + *this = ::std::move(from); + } + + inline ServerToClient& operator=(const ServerToClient& from) { + CopyFrom(from); + return *this; + } + inline ServerToClient& operator=(ServerToClient&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ServerToClient& default_instance() { + return *internal_default_instance(); + } + static inline const ServerToClient* internal_default_instance() { + return reinterpret_cast( + &_ServerToClient_default_instance_); + } + static constexpr int kIndexInFileMessages = + 6; + + friend void swap(ServerToClient& a, ServerToClient& b) { + a.Swap(&b); + } + inline void Swap(ServerToClient* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ServerToClient* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ServerToClient* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const ServerToClient& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const ServerToClient& from) { + ServerToClient::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(ServerToClient* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "ServerToClient"; + } + protected: + explicit ServerToClient(::google::protobuf::Arena* arena); + ServerToClient(::google::protobuf::Arena* arena, const ServerToClient& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kPlayerStatesFieldNumber = 8, + kPlayerUpdatesFieldNumber = 9, + kTag1FieldNumber = 1, + kRiderIdFieldNumber = 2, + kWorldTimeFieldNumber = 3, + kTag11FieldNumber = 11, + kSeqnoFieldNumber = 4, + kNumMsgsFieldNumber = 18, + kTag17FieldNumber = 17, + kMsgnumFieldNumber = 19, + }; + // repeated .PlayerState player_states = 8; + int player_states_size() const; + private: + int _internal_player_states_size() const; + + public: + void clear_player_states() ; + ::PlayerState* mutable_player_states(int index); + ::google::protobuf::RepeatedPtrField< ::PlayerState >* + mutable_player_states(); + private: + const ::google::protobuf::RepeatedPtrField<::PlayerState>& _internal_player_states() const; + ::google::protobuf::RepeatedPtrField<::PlayerState>* _internal_mutable_player_states(); + public: + const ::PlayerState& player_states(int index) const; + ::PlayerState* add_player_states(); + const ::google::protobuf::RepeatedPtrField< ::PlayerState >& + player_states() const; + // repeated .UnknownMessage player_updates = 9; + int player_updates_size() const; + private: + int _internal_player_updates_size() const; + + public: + void clear_player_updates() ; + ::UnknownMessage* mutable_player_updates(int index); + ::google::protobuf::RepeatedPtrField< ::UnknownMessage >* + mutable_player_updates(); + private: + const ::google::protobuf::RepeatedPtrField<::UnknownMessage>& _internal_player_updates() const; + ::google::protobuf::RepeatedPtrField<::UnknownMessage>* _internal_mutable_player_updates(); + public: + const ::UnknownMessage& player_updates(int index) const; + ::UnknownMessage* add_player_updates(); + const ::google::protobuf::RepeatedPtrField< ::UnknownMessage >& + player_updates() const; + // int32 tag1 = 1; + void clear_tag1() ; + ::int32_t tag1() const; + void set_tag1(::int32_t value); + + private: + ::int32_t _internal_tag1() const; + void _internal_set_tag1(::int32_t value); + + public: + // int32 rider_id = 2; + void clear_rider_id() ; + ::int32_t rider_id() const; + void set_rider_id(::int32_t value); + + private: + ::int32_t _internal_rider_id() const; + void _internal_set_rider_id(::int32_t value); + + public: + // int64 world_time = 3; + void clear_world_time() ; + ::int64_t world_time() const; + void set_world_time(::int64_t value); + + private: + ::int64_t _internal_world_time() const; + void _internal_set_world_time(::int64_t value); + + public: + // int64 tag11 = 11; + void clear_tag11() ; + ::int64_t tag11() const; + void set_tag11(::int64_t value); + + private: + ::int64_t _internal_tag11() const; + void _internal_set_tag11(::int64_t value); + + public: + // int32 seqno = 4; + void clear_seqno() ; + ::int32_t seqno() const; + void set_seqno(::int32_t value); + + private: + ::int32_t _internal_seqno() const; + void _internal_set_seqno(::int32_t value); + + public: + // int32 num_msgs = 18; + void clear_num_msgs() ; + ::int32_t num_msgs() const; + void set_num_msgs(::int32_t value); + + private: + ::int32_t _internal_num_msgs() const; + void _internal_set_num_msgs(::int32_t value); + + public: + // int64 tag17 = 17; + void clear_tag17() ; + ::int64_t tag17() const; + void set_tag17(::int64_t value); + + private: + ::int64_t _internal_tag17() const; + void _internal_set_tag17(::int64_t value); + + public: + // int32 msgnum = 19; + void clear_msgnum() ; + ::int32_t msgnum() const; + void set_msgnum(::int32_t value); + + private: + ::int32_t _internal_msgnum() const; + void _internal_set_msgnum(::int32_t value); + + public: + // @@protoc_insertion_point(class_scope:ServerToClient) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 4, 10, 2, + 0, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::RepeatedPtrField< ::PlayerState > player_states_; + ::google::protobuf::RepeatedPtrField< ::UnknownMessage > player_updates_; + ::int32_t tag1_; + ::int32_t rider_id_; + ::int64_t world_time_; + ::int64_t tag11_; + ::int32_t seqno_; + ::int32_t num_msgs_; + ::int64_t tag17_; + ::int32_t msgnum_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class SegmentResults final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:SegmentResults) */ { + public: + inline SegmentResults() : SegmentResults(nullptr) {} + ~SegmentResults() override; + template + explicit PROTOBUF_CONSTEXPR SegmentResults(::google::protobuf::internal::ConstantInitialized); + + inline SegmentResults(const SegmentResults& from) + : SegmentResults(nullptr, from) {} + SegmentResults(SegmentResults&& from) noexcept + : SegmentResults() { + *this = ::std::move(from); + } + + inline SegmentResults& operator=(const SegmentResults& from) { + CopyFrom(from); + return *this; + } + inline SegmentResults& operator=(SegmentResults&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SegmentResults& default_instance() { + return *internal_default_instance(); + } + static inline const SegmentResults* internal_default_instance() { + return reinterpret_cast( + &_SegmentResults_default_instance_); + } + static constexpr int kIndexInFileMessages = + 3; + + friend void swap(SegmentResults& a, SegmentResults& b) { + a.Swap(&b); + } + inline void Swap(SegmentResults* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SegmentResults* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SegmentResults* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const SegmentResults& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const SegmentResults& from) { + SegmentResults::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(SegmentResults* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "SegmentResults"; + } + protected: + explicit SegmentResults(::google::protobuf::Arena* arena); + SegmentResults(::google::protobuf::Arena* arena, const SegmentResults& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kSegmentResultsFieldNumber = 4, + kWorldIdFieldNumber = 1, + kSegmentIdFieldNumber = 2, + kEventSubgroupIdFieldNumber = 3, + }; + // repeated .SegmentResult segment_results = 4; + int segment_results_size() const; + private: + int _internal_segment_results_size() const; + + public: + void clear_segment_results() ; + ::SegmentResult* mutable_segment_results(int index); + ::google::protobuf::RepeatedPtrField< ::SegmentResult >* + mutable_segment_results(); + private: + const ::google::protobuf::RepeatedPtrField<::SegmentResult>& _internal_segment_results() const; + ::google::protobuf::RepeatedPtrField<::SegmentResult>* _internal_mutable_segment_results(); + public: + const ::SegmentResult& segment_results(int index) const; + ::SegmentResult* add_segment_results(); + const ::google::protobuf::RepeatedPtrField< ::SegmentResult >& + segment_results() const; + // int64 world_id = 1; + void clear_world_id() ; + ::int64_t world_id() const; + void set_world_id(::int64_t value); + + private: + ::int64_t _internal_world_id() const; + void _internal_set_world_id(::int64_t value); + + public: + // int64 segment_id = 2; + void clear_segment_id() ; + ::int64_t segment_id() const; + void set_segment_id(::int64_t value); + + private: + ::int64_t _internal_segment_id() const; + void _internal_set_segment_id(::int64_t value); + + public: + // int64 event_subgroup_id = 3; + void clear_event_subgroup_id() ; + ::int64_t event_subgroup_id() const; + void set_event_subgroup_id(::int64_t value); + + private: + ::int64_t _internal_event_subgroup_id() const; + void _internal_set_event_subgroup_id(::int64_t value); + + public: + // @@protoc_insertion_point(class_scope:SegmentResults) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 2, 4, 1, + 0, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::RepeatedPtrField< ::SegmentResult > segment_results_; + ::int64_t world_id_; + ::int64_t segment_id_; + ::int64_t event_subgroup_id_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class RiderAttributes final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:RiderAttributes) */ { + public: + inline RiderAttributes() : RiderAttributes(nullptr) {} + ~RiderAttributes() override; + template + explicit PROTOBUF_CONSTEXPR RiderAttributes(::google::protobuf::internal::ConstantInitialized); + + inline RiderAttributes(const RiderAttributes& from) + : RiderAttributes(nullptr, from) {} + RiderAttributes(RiderAttributes&& from) noexcept + : RiderAttributes() { + *this = ::std::move(from); + } + + inline RiderAttributes& operator=(const RiderAttributes& from) { + CopyFrom(from); + return *this; + } + inline RiderAttributes& operator=(RiderAttributes&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const RiderAttributes& default_instance() { + return *internal_default_instance(); + } + static inline const RiderAttributes* internal_default_instance() { + return reinterpret_cast( + &_RiderAttributes_default_instance_); + } + static constexpr int kIndexInFileMessages = + 11; + + friend void swap(RiderAttributes& a, RiderAttributes& b) { + a.Swap(&b); + } + inline void Swap(RiderAttributes* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(RiderAttributes* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + RiderAttributes* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const RiderAttributes& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const RiderAttributes& from) { + RiderAttributes::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(RiderAttributes* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "RiderAttributes"; + } + protected: + explicit RiderAttributes(::google::protobuf::Arena* arena); + RiderAttributes(::google::protobuf::Arena* arena, const RiderAttributes& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + using AttributeMessage = RiderAttributes_AttributeMessage; + + // accessors ------------------------------------------------------- + + enum : int { + kAttributeMessageFieldNumber = 4, + kF2FieldNumber = 2, + kF3FieldNumber = 3, + kTheirIdFieldNumber = 10, + kF13FieldNumber = 13, + }; + // .RiderAttributes.AttributeMessage attributeMessage = 4; + bool has_attributemessage() const; + void clear_attributemessage() ; + const ::RiderAttributes_AttributeMessage& attributemessage() const; + PROTOBUF_NODISCARD ::RiderAttributes_AttributeMessage* release_attributemessage(); + ::RiderAttributes_AttributeMessage* mutable_attributemessage(); + void set_allocated_attributemessage(::RiderAttributes_AttributeMessage* value); + void unsafe_arena_set_allocated_attributemessage(::RiderAttributes_AttributeMessage* value); + ::RiderAttributes_AttributeMessage* unsafe_arena_release_attributemessage(); + + private: + const ::RiderAttributes_AttributeMessage& _internal_attributemessage() const; + ::RiderAttributes_AttributeMessage* _internal_mutable_attributemessage(); + + public: + // int32 f2 = 2; + void clear_f2() ; + ::int32_t f2() const; + void set_f2(::int32_t value); + + private: + ::int32_t _internal_f2() const; + void _internal_set_f2(::int32_t value); + + public: + // int32 f3 = 3; + void clear_f3() ; + ::int32_t f3() const; + void set_f3(::int32_t value); + + private: + ::int32_t _internal_f3() const; + void _internal_set_f3(::int32_t value); + + public: + // int32 theirId = 10; + void clear_theirid() ; + ::int32_t theirid() const; + void set_theirid(::int32_t value); + + private: + ::int32_t _internal_theirid() const; + void _internal_set_theirid(::int32_t value); + + public: + // int32 f13 = 13; + void clear_f13() ; + ::int32_t f13() const; + void set_f13(::int32_t value); + + private: + ::int32_t _internal_f13() const; + void _internal_set_f13(::int32_t value); + + public: + // @@protoc_insertion_point(class_scope:RiderAttributes) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 2, 5, 1, + 0, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::HasBits<1> _has_bits_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::RiderAttributes_AttributeMessage* attributemessage_; + ::int32_t f2_; + ::int32_t f3_; + ::int32_t theirid_; + ::int32_t f13_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class Profiles final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:Profiles) */ { + public: + inline Profiles() : Profiles(nullptr) {} + ~Profiles() override; + template + explicit PROTOBUF_CONSTEXPR Profiles(::google::protobuf::internal::ConstantInitialized); + + inline Profiles(const Profiles& from) + : Profiles(nullptr, from) {} + Profiles(Profiles&& from) noexcept + : Profiles() { + *this = ::std::move(from); + } + + inline Profiles& operator=(const Profiles& from) { + CopyFrom(from); + return *this; + } + inline Profiles& operator=(Profiles&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Profiles& default_instance() { + return *internal_default_instance(); + } + static inline const Profiles* internal_default_instance() { + return reinterpret_cast( + &_Profiles_default_instance_); + } + static constexpr int kIndexInFileMessages = + 12; + + friend void swap(Profiles& a, Profiles& b) { + a.Swap(&b); + } + inline void Swap(Profiles* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Profiles* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Profiles* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const Profiles& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const Profiles& from) { + Profiles::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(Profiles* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "Profiles"; + } + protected: + explicit Profiles(::google::protobuf::Arena* arena); + Profiles(::google::protobuf::Arena* arena, const Profiles& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kProfilesFieldNumber = 1, + }; + // repeated .Profile profiles = 1; + int profiles_size() const; + private: + int _internal_profiles_size() const; + + public: + void clear_profiles() ; + ::Profile* mutable_profiles(int index); + ::google::protobuf::RepeatedPtrField< ::Profile >* + mutable_profiles(); + private: + const ::google::protobuf::RepeatedPtrField<::Profile>& _internal_profiles() const; + ::google::protobuf::RepeatedPtrField<::Profile>* _internal_mutable_profiles(); + public: + const ::Profile& profiles(int index) const; + ::Profile* add_profiles(); + const ::google::protobuf::RepeatedPtrField< ::Profile >& + profiles() const; + // @@protoc_insertion_point(class_scope:Profiles) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 0, 1, 1, + 0, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::RepeatedPtrField< ::Profile > profiles_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +};// ------------------------------------------------------------------- + +class ClientToServer final : + public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:ClientToServer) */ { + public: + inline ClientToServer() : ClientToServer(nullptr) {} + ~ClientToServer() override; + template + explicit PROTOBUF_CONSTEXPR ClientToServer(::google::protobuf::internal::ConstantInitialized); + + inline ClientToServer(const ClientToServer& from) + : ClientToServer(nullptr, from) {} + ClientToServer(ClientToServer&& from) noexcept + : ClientToServer() { + *this = ::std::move(from); + } + + inline ClientToServer& operator=(const ClientToServer& from) { + CopyFrom(from); + return *this; + } + inline ClientToServer& operator=(ClientToServer&& from) noexcept { + if (this == &from) return *this; + if (GetArena() == from.GetArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance); + } + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>(); + } + + static const ::google::protobuf::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::google::protobuf::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::google::protobuf::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ClientToServer& default_instance() { + return *internal_default_instance(); + } + static inline const ClientToServer* internal_default_instance() { + return reinterpret_cast( + &_ClientToServer_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(ClientToServer& a, ClientToServer& b) { + a.Swap(&b); + } + inline void Swap(ClientToServer* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() != nullptr && + GetArena() == other->GetArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetArena() == other->GetArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::google::protobuf::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ClientToServer* other) { + if (other == this) return; + ABSL_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ClientToServer* New(::google::protobuf::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::google::protobuf::Message::CopyFrom; + void CopyFrom(const ClientToServer& from); + using ::google::protobuf::Message::MergeFrom; + void MergeFrom( const ClientToServer& from) { + ClientToServer::MergeImpl(*this, from); + } + private: + static void MergeImpl(::google::protobuf::Message& to_msg, const ::google::protobuf::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + ::size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::google::protobuf::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const { return _impl_._cached_size_.Get(); } + + private: + ::google::protobuf::internal::CachedSize* AccessCachedSize() const final; + void SharedCtor(::google::protobuf::Arena* arena); + void SharedDtor(); + void InternalSwap(ClientToServer* other); + + private: + friend class ::google::protobuf::internal::AnyMetadata; + static ::absl::string_view FullMessageName() { + return "ClientToServer"; + } + protected: + explicit ClientToServer(::google::protobuf::Arena* arena); + ClientToServer(::google::protobuf::Arena* arena, const ClientToServer& from); + public: + + static const ClassData _class_data_; + const ::google::protobuf::Message::ClassData*GetClassData() const final; + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kStateFieldNumber = 7, + kConnectedFieldNumber = 1, + kRiderIdFieldNumber = 2, + kWorldTimeFieldNumber = 3, + kTag8FieldNumber = 8, + kTag9FieldNumber = 9, + kLastUpdateFieldNumber = 10, + kTag11FieldNumber = 11, + kLastPlayerUpdateFieldNumber = 12, + kSeqnoFieldNumber = 4, + }; + // .PlayerState state = 7; + bool has_state() const; + void clear_state() ; + const ::PlayerState& state() const; + PROTOBUF_NODISCARD ::PlayerState* release_state(); + ::PlayerState* mutable_state(); + void set_allocated_state(::PlayerState* value); + void unsafe_arena_set_allocated_state(::PlayerState* value); + ::PlayerState* unsafe_arena_release_state(); + + private: + const ::PlayerState& _internal_state() const; + ::PlayerState* _internal_mutable_state(); + + public: + // int32 connected = 1; + void clear_connected() ; + ::int32_t connected() const; + void set_connected(::int32_t value); + + private: + ::int32_t _internal_connected() const; + void _internal_set_connected(::int32_t value); + + public: + // int32 rider_id = 2; + void clear_rider_id() ; + ::int32_t rider_id() const; + void set_rider_id(::int32_t value); + + private: + ::int32_t _internal_rider_id() const; + void _internal_set_rider_id(::int32_t value); + + public: + // int64 world_time = 3; + void clear_world_time() ; + ::int64_t world_time() const; + void set_world_time(::int64_t value); + + private: + ::int64_t _internal_world_time() const; + void _internal_set_world_time(::int64_t value); + + public: + // int64 tag8 = 8; + void clear_tag8() ; + ::int64_t tag8() const; + void set_tag8(::int64_t value); + + private: + ::int64_t _internal_tag8() const; + void _internal_set_tag8(::int64_t value); + + public: + // int64 tag9 = 9; + void clear_tag9() ; + ::int64_t tag9() const; + void set_tag9(::int64_t value); + + private: + ::int64_t _internal_tag9() const; + void _internal_set_tag9(::int64_t value); + + public: + // int64 last_update = 10; + void clear_last_update() ; + ::int64_t last_update() const; + void set_last_update(::int64_t value); + + private: + ::int64_t _internal_last_update() const; + void _internal_set_last_update(::int64_t value); + + public: + // int64 tag11 = 11; + void clear_tag11() ; + ::int64_t tag11() const; + void set_tag11(::int64_t value); + + private: + ::int64_t _internal_tag11() const; + void _internal_set_tag11(::int64_t value); + + public: + // int64 last_player_update = 12; + void clear_last_player_update() ; + ::int64_t last_player_update() const; + void set_last_player_update(::int64_t value); + + private: + ::int64_t _internal_last_player_update() const; + void _internal_set_last_player_update(::int64_t value); + + public: + // int32 seqno = 4; + void clear_seqno() ; + ::int32_t seqno() const; + void set_seqno(::int32_t value); + + private: + ::int32_t _internal_seqno() const; + void _internal_set_seqno(::int32_t value); + + public: + // @@protoc_insertion_point(class_scope:ClientToServer) + private: + class _Internal; + + friend class ::google::protobuf::internal::TcParser; + static const ::google::protobuf::internal::TcParseTable< + 4, 10, 1, + 0, 2> + _table_; + friend class ::google::protobuf::MessageLite; + friend class ::google::protobuf::Arena; + template + friend class ::google::protobuf::Arena::InternalHelper; + using InternalArenaConstructable_ = void; + using DestructorSkippable_ = void; + struct Impl_ { + + inline explicit constexpr Impl_( + ::google::protobuf::internal::ConstantInitialized) noexcept; + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena); + inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility, + ::google::protobuf::Arena* arena, const Impl_& from); + ::google::protobuf::internal::HasBits<1> _has_bits_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::PlayerState* state_; + ::int32_t connected_; + ::int32_t rider_id_; + ::int64_t world_time_; + ::int64_t tag8_; + ::int64_t tag9_; + ::int64_t last_update_; + ::int64_t tag11_; + ::int64_t last_player_update_; + ::int32_t seqno_; + PROTOBUF_TSAN_DECLARE_MEMBER + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_zwift_5fmessages_2eproto; +}; + +// =================================================================== + + + + +// =================================================================== + + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// PlayerState + +// int32 id = 1; +inline void PlayerState::clear_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.id_ = 0; +} +inline ::int32_t PlayerState::id() const { + // @@protoc_insertion_point(field_get:PlayerState.id) + return _internal_id(); +} +inline void PlayerState::set_id(::int32_t value) { + _internal_set_id(value); + // @@protoc_insertion_point(field_set:PlayerState.id) +} +inline ::int32_t PlayerState::_internal_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.id_; +} +inline void PlayerState::_internal_set_id(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.id_ = value; +} + +// int64 worldTime = 2; +inline void PlayerState::clear_worldtime() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.worldtime_ = ::int64_t{0}; +} +inline ::int64_t PlayerState::worldtime() const { + // @@protoc_insertion_point(field_get:PlayerState.worldTime) + return _internal_worldtime(); +} +inline void PlayerState::set_worldtime(::int64_t value) { + _internal_set_worldtime(value); + // @@protoc_insertion_point(field_set:PlayerState.worldTime) +} +inline ::int64_t PlayerState::_internal_worldtime() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.worldtime_; +} +inline void PlayerState::_internal_set_worldtime(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.worldtime_ = value; +} + +// int32 distance = 3; +inline void PlayerState::clear_distance() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.distance_ = 0; +} +inline ::int32_t PlayerState::distance() const { + // @@protoc_insertion_point(field_get:PlayerState.distance) + return _internal_distance(); +} +inline void PlayerState::set_distance(::int32_t value) { + _internal_set_distance(value); + // @@protoc_insertion_point(field_set:PlayerState.distance) +} +inline ::int32_t PlayerState::_internal_distance() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.distance_; +} +inline void PlayerState::_internal_set_distance(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.distance_ = value; +} + +// int32 roadTime = 4; +inline void PlayerState::clear_roadtime() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.roadtime_ = 0; +} +inline ::int32_t PlayerState::roadtime() const { + // @@protoc_insertion_point(field_get:PlayerState.roadTime) + return _internal_roadtime(); +} +inline void PlayerState::set_roadtime(::int32_t value) { + _internal_set_roadtime(value); + // @@protoc_insertion_point(field_set:PlayerState.roadTime) +} +inline ::int32_t PlayerState::_internal_roadtime() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.roadtime_; +} +inline void PlayerState::_internal_set_roadtime(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.roadtime_ = value; +} + +// int32 laps = 5; +inline void PlayerState::clear_laps() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.laps_ = 0; +} +inline ::int32_t PlayerState::laps() const { + // @@protoc_insertion_point(field_get:PlayerState.laps) + return _internal_laps(); +} +inline void PlayerState::set_laps(::int32_t value) { + _internal_set_laps(value); + // @@protoc_insertion_point(field_set:PlayerState.laps) +} +inline ::int32_t PlayerState::_internal_laps() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.laps_; +} +inline void PlayerState::_internal_set_laps(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.laps_ = value; +} + +// int32 speed = 6; +inline void PlayerState::clear_speed() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.speed_ = 0; +} +inline ::int32_t PlayerState::speed() const { + // @@protoc_insertion_point(field_get:PlayerState.speed) + return _internal_speed(); +} +inline void PlayerState::set_speed(::int32_t value) { + _internal_set_speed(value); + // @@protoc_insertion_point(field_set:PlayerState.speed) +} +inline ::int32_t PlayerState::_internal_speed() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.speed_; +} +inline void PlayerState::_internal_set_speed(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.speed_ = value; +} + +// int32 roadPosition = 8; +inline void PlayerState::clear_roadposition() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.roadposition_ = 0; +} +inline ::int32_t PlayerState::roadposition() const { + // @@protoc_insertion_point(field_get:PlayerState.roadPosition) + return _internal_roadposition(); +} +inline void PlayerState::set_roadposition(::int32_t value) { + _internal_set_roadposition(value); + // @@protoc_insertion_point(field_set:PlayerState.roadPosition) +} +inline ::int32_t PlayerState::_internal_roadposition() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.roadposition_; +} +inline void PlayerState::_internal_set_roadposition(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.roadposition_ = value; +} + +// int32 cadenceUHz = 9; +inline void PlayerState::clear_cadenceuhz() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.cadenceuhz_ = 0; +} +inline ::int32_t PlayerState::cadenceuhz() const { + // @@protoc_insertion_point(field_get:PlayerState.cadenceUHz) + return _internal_cadenceuhz(); +} +inline void PlayerState::set_cadenceuhz(::int32_t value) { + _internal_set_cadenceuhz(value); + // @@protoc_insertion_point(field_set:PlayerState.cadenceUHz) +} +inline ::int32_t PlayerState::_internal_cadenceuhz() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.cadenceuhz_; +} +inline void PlayerState::_internal_set_cadenceuhz(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.cadenceuhz_ = value; +} + +// int32 heartrate = 11; +inline void PlayerState::clear_heartrate() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.heartrate_ = 0; +} +inline ::int32_t PlayerState::heartrate() const { + // @@protoc_insertion_point(field_get:PlayerState.heartrate) + return _internal_heartrate(); +} +inline void PlayerState::set_heartrate(::int32_t value) { + _internal_set_heartrate(value); + // @@protoc_insertion_point(field_set:PlayerState.heartrate) +} +inline ::int32_t PlayerState::_internal_heartrate() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.heartrate_; +} +inline void PlayerState::_internal_set_heartrate(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.heartrate_ = value; +} + +// int32 power = 12; +inline void PlayerState::clear_power() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.power_ = 0; +} +inline ::int32_t PlayerState::power() const { + // @@protoc_insertion_point(field_get:PlayerState.power) + return _internal_power(); +} +inline void PlayerState::set_power(::int32_t value) { + _internal_set_power(value); + // @@protoc_insertion_point(field_set:PlayerState.power) +} +inline ::int32_t PlayerState::_internal_power() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.power_; +} +inline void PlayerState::_internal_set_power(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.power_ = value; +} + +// int64 heading = 13; +inline void PlayerState::clear_heading() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.heading_ = ::int64_t{0}; +} +inline ::int64_t PlayerState::heading() const { + // @@protoc_insertion_point(field_get:PlayerState.heading) + return _internal_heading(); +} +inline void PlayerState::set_heading(::int64_t value) { + _internal_set_heading(value); + // @@protoc_insertion_point(field_set:PlayerState.heading) +} +inline ::int64_t PlayerState::_internal_heading() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.heading_; +} +inline void PlayerState::_internal_set_heading(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.heading_ = value; +} + +// int32 lean = 14; +inline void PlayerState::clear_lean() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.lean_ = 0; +} +inline ::int32_t PlayerState::lean() const { + // @@protoc_insertion_point(field_get:PlayerState.lean) + return _internal_lean(); +} +inline void PlayerState::set_lean(::int32_t value) { + _internal_set_lean(value); + // @@protoc_insertion_point(field_set:PlayerState.lean) +} +inline ::int32_t PlayerState::_internal_lean() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.lean_; +} +inline void PlayerState::_internal_set_lean(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.lean_ = value; +} + +// int32 climbing = 15; +inline void PlayerState::clear_climbing() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.climbing_ = 0; +} +inline ::int32_t PlayerState::climbing() const { + // @@protoc_insertion_point(field_get:PlayerState.climbing) + return _internal_climbing(); +} +inline void PlayerState::set_climbing(::int32_t value) { + _internal_set_climbing(value); + // @@protoc_insertion_point(field_set:PlayerState.climbing) +} +inline ::int32_t PlayerState::_internal_climbing() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.climbing_; +} +inline void PlayerState::_internal_set_climbing(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.climbing_ = value; +} + +// int32 time = 16; +inline void PlayerState::clear_time() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.time_ = 0; +} +inline ::int32_t PlayerState::time() const { + // @@protoc_insertion_point(field_get:PlayerState.time) + return _internal_time(); +} +inline void PlayerState::set_time(::int32_t value) { + _internal_set_time(value); + // @@protoc_insertion_point(field_set:PlayerState.time) +} +inline ::int32_t PlayerState::_internal_time() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.time_; +} +inline void PlayerState::_internal_set_time(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.time_ = value; +} + +// int32 f19 = 19; +inline void PlayerState::clear_f19() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.f19_ = 0; +} +inline ::int32_t PlayerState::f19() const { + // @@protoc_insertion_point(field_get:PlayerState.f19) + return _internal_f19(); +} +inline void PlayerState::set_f19(::int32_t value) { + _internal_set_f19(value); + // @@protoc_insertion_point(field_set:PlayerState.f19) +} +inline ::int32_t PlayerState::_internal_f19() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.f19_; +} +inline void PlayerState::_internal_set_f19(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.f19_ = value; +} + +// int32 f20 = 20; +inline void PlayerState::clear_f20() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.f20_ = 0; +} +inline ::int32_t PlayerState::f20() const { + // @@protoc_insertion_point(field_get:PlayerState.f20) + return _internal_f20(); +} +inline void PlayerState::set_f20(::int32_t value) { + _internal_set_f20(value); + // @@protoc_insertion_point(field_set:PlayerState.f20) +} +inline ::int32_t PlayerState::_internal_f20() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.f20_; +} +inline void PlayerState::_internal_set_f20(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.f20_ = value; +} + +// int32 progress = 21; +inline void PlayerState::clear_progress() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.progress_ = 0; +} +inline ::int32_t PlayerState::progress() const { + // @@protoc_insertion_point(field_get:PlayerState.progress) + return _internal_progress(); +} +inline void PlayerState::set_progress(::int32_t value) { + _internal_set_progress(value); + // @@protoc_insertion_point(field_set:PlayerState.progress) +} +inline ::int32_t PlayerState::_internal_progress() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.progress_; +} +inline void PlayerState::_internal_set_progress(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.progress_ = value; +} + +// int64 customisationId = 22; +inline void PlayerState::clear_customisationid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.customisationid_ = ::int64_t{0}; +} +inline ::int64_t PlayerState::customisationid() const { + // @@protoc_insertion_point(field_get:PlayerState.customisationId) + return _internal_customisationid(); +} +inline void PlayerState::set_customisationid(::int64_t value) { + _internal_set_customisationid(value); + // @@protoc_insertion_point(field_set:PlayerState.customisationId) +} +inline ::int64_t PlayerState::_internal_customisationid() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.customisationid_; +} +inline void PlayerState::_internal_set_customisationid(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.customisationid_ = value; +} + +// int32 justWatching = 23; +inline void PlayerState::clear_justwatching() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.justwatching_ = 0; +} +inline ::int32_t PlayerState::justwatching() const { + // @@protoc_insertion_point(field_get:PlayerState.justWatching) + return _internal_justwatching(); +} +inline void PlayerState::set_justwatching(::int32_t value) { + _internal_set_justwatching(value); + // @@protoc_insertion_point(field_set:PlayerState.justWatching) +} +inline ::int32_t PlayerState::_internal_justwatching() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.justwatching_; +} +inline void PlayerState::_internal_set_justwatching(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.justwatching_ = value; +} + +// int32 calories = 24; +inline void PlayerState::clear_calories() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.calories_ = 0; +} +inline ::int32_t PlayerState::calories() const { + // @@protoc_insertion_point(field_get:PlayerState.calories) + return _internal_calories(); +} +inline void PlayerState::set_calories(::int32_t value) { + _internal_set_calories(value); + // @@protoc_insertion_point(field_set:PlayerState.calories) +} +inline ::int32_t PlayerState::_internal_calories() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.calories_; +} +inline void PlayerState::_internal_set_calories(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.calories_ = value; +} + +// float x = 25; +inline void PlayerState::clear_x() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.x_ = 0; +} +inline float PlayerState::x() const { + // @@protoc_insertion_point(field_get:PlayerState.x) + return _internal_x(); +} +inline void PlayerState::set_x(float value) { + _internal_set_x(value); + // @@protoc_insertion_point(field_set:PlayerState.x) +} +inline float PlayerState::_internal_x() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.x_; +} +inline void PlayerState::_internal_set_x(float value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.x_ = value; +} + +// float altitude = 26; +inline void PlayerState::clear_altitude() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.altitude_ = 0; +} +inline float PlayerState::altitude() const { + // @@protoc_insertion_point(field_get:PlayerState.altitude) + return _internal_altitude(); +} +inline void PlayerState::set_altitude(float value) { + _internal_set_altitude(value); + // @@protoc_insertion_point(field_set:PlayerState.altitude) +} +inline float PlayerState::_internal_altitude() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.altitude_; +} +inline void PlayerState::_internal_set_altitude(float value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.altitude_ = value; +} + +// float y = 27; +inline void PlayerState::clear_y() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.y_ = 0; +} +inline float PlayerState::y() const { + // @@protoc_insertion_point(field_get:PlayerState.y) + return _internal_y(); +} +inline void PlayerState::set_y(float value) { + _internal_set_y(value); + // @@protoc_insertion_point(field_set:PlayerState.y) +} +inline float PlayerState::_internal_y() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.y_; +} +inline void PlayerState::_internal_set_y(float value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.y_ = value; +} + +// int32 watchingRiderId = 28; +inline void PlayerState::clear_watchingriderid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.watchingriderid_ = 0; +} +inline ::int32_t PlayerState::watchingriderid() const { + // @@protoc_insertion_point(field_get:PlayerState.watchingRiderId) + return _internal_watchingriderid(); +} +inline void PlayerState::set_watchingriderid(::int32_t value) { + _internal_set_watchingriderid(value); + // @@protoc_insertion_point(field_set:PlayerState.watchingRiderId) +} +inline ::int32_t PlayerState::_internal_watchingriderid() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.watchingriderid_; +} +inline void PlayerState::_internal_set_watchingriderid(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.watchingriderid_ = value; +} + +// int32 groupId = 29; +inline void PlayerState::clear_groupid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.groupid_ = 0; +} +inline ::int32_t PlayerState::groupid() const { + // @@protoc_insertion_point(field_get:PlayerState.groupId) + return _internal_groupid(); +} +inline void PlayerState::set_groupid(::int32_t value) { + _internal_set_groupid(value); + // @@protoc_insertion_point(field_set:PlayerState.groupId) +} +inline ::int32_t PlayerState::_internal_groupid() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.groupid_; +} +inline void PlayerState::_internal_set_groupid(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.groupid_ = value; +} + +// int64 sport = 31; +inline void PlayerState::clear_sport() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.sport_ = ::int64_t{0}; +} +inline ::int64_t PlayerState::sport() const { + // @@protoc_insertion_point(field_get:PlayerState.sport) + return _internal_sport(); +} +inline void PlayerState::set_sport(::int64_t value) { + _internal_set_sport(value); + // @@protoc_insertion_point(field_set:PlayerState.sport) +} +inline ::int64_t PlayerState::_internal_sport() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.sport_; +} +inline void PlayerState::_internal_set_sport(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.sport_ = value; +} + +// ------------------------------------------------------------------- + +// ClientToServer + +// int32 connected = 1; +inline void ClientToServer::clear_connected() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.connected_ = 0; +} +inline ::int32_t ClientToServer::connected() const { + // @@protoc_insertion_point(field_get:ClientToServer.connected) + return _internal_connected(); +} +inline void ClientToServer::set_connected(::int32_t value) { + _internal_set_connected(value); + // @@protoc_insertion_point(field_set:ClientToServer.connected) +} +inline ::int32_t ClientToServer::_internal_connected() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.connected_; +} +inline void ClientToServer::_internal_set_connected(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.connected_ = value; +} + +// int32 rider_id = 2; +inline void ClientToServer::clear_rider_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.rider_id_ = 0; +} +inline ::int32_t ClientToServer::rider_id() const { + // @@protoc_insertion_point(field_get:ClientToServer.rider_id) + return _internal_rider_id(); +} +inline void ClientToServer::set_rider_id(::int32_t value) { + _internal_set_rider_id(value); + // @@protoc_insertion_point(field_set:ClientToServer.rider_id) +} +inline ::int32_t ClientToServer::_internal_rider_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.rider_id_; +} +inline void ClientToServer::_internal_set_rider_id(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.rider_id_ = value; +} + +// int64 world_time = 3; +inline void ClientToServer::clear_world_time() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.world_time_ = ::int64_t{0}; +} +inline ::int64_t ClientToServer::world_time() const { + // @@protoc_insertion_point(field_get:ClientToServer.world_time) + return _internal_world_time(); +} +inline void ClientToServer::set_world_time(::int64_t value) { + _internal_set_world_time(value); + // @@protoc_insertion_point(field_set:ClientToServer.world_time) +} +inline ::int64_t ClientToServer::_internal_world_time() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.world_time_; +} +inline void ClientToServer::_internal_set_world_time(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.world_time_ = value; +} + +// .PlayerState state = 7; +inline bool ClientToServer::has_state() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + PROTOBUF_ASSUME(!value || _impl_.state_ != nullptr); + return value; +} +inline void ClientToServer::clear_state() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (_impl_.state_ != nullptr) _impl_.state_->Clear(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const ::PlayerState& ClientToServer::_internal_state() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + const ::PlayerState* p = _impl_.state_; + return p != nullptr ? *p : reinterpret_cast(::_PlayerState_default_instance_); +} +inline const ::PlayerState& ClientToServer::state() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:ClientToServer.state) + return _internal_state(); +} +inline void ClientToServer::unsafe_arena_set_allocated_state(::PlayerState* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.state_); + } + _impl_.state_ = reinterpret_cast<::PlayerState*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:ClientToServer.state) +} +inline ::PlayerState* ClientToServer::release_state() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + + _impl_._has_bits_[0] &= ~0x00000001u; + ::PlayerState* released = _impl_.state_; + _impl_.state_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return released; +} +inline ::PlayerState* ClientToServer::unsafe_arena_release_state() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:ClientToServer.state) + + _impl_._has_bits_[0] &= ~0x00000001u; + ::PlayerState* temp = _impl_.state_; + _impl_.state_ = nullptr; + return temp; +} +inline ::PlayerState* ClientToServer::_internal_mutable_state() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000001u; + if (_impl_.state_ == nullptr) { + auto* p = CreateMaybeMessage<::PlayerState>(GetArena()); + _impl_.state_ = reinterpret_cast<::PlayerState*>(p); + } + return _impl_.state_; +} +inline ::PlayerState* ClientToServer::mutable_state() ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::PlayerState* _msg = _internal_mutable_state(); + // @@protoc_insertion_point(field_mutable:ClientToServer.state) + return _msg; +} +inline void ClientToServer::set_allocated_state(::PlayerState* value) { + ::google::protobuf::Arena* message_arena = GetArena(); + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (message_arena == nullptr) { + delete reinterpret_cast<::PlayerState*>(_impl_.state_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::PlayerState*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + + _impl_.state_ = reinterpret_cast<::PlayerState*>(value); + // @@protoc_insertion_point(field_set_allocated:ClientToServer.state) +} + +// int32 seqno = 4; +inline void ClientToServer::clear_seqno() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.seqno_ = 0; +} +inline ::int32_t ClientToServer::seqno() const { + // @@protoc_insertion_point(field_get:ClientToServer.seqno) + return _internal_seqno(); +} +inline void ClientToServer::set_seqno(::int32_t value) { + _internal_set_seqno(value); + // @@protoc_insertion_point(field_set:ClientToServer.seqno) +} +inline ::int32_t ClientToServer::_internal_seqno() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.seqno_; +} +inline void ClientToServer::_internal_set_seqno(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.seqno_ = value; +} + +// int64 tag8 = 8; +inline void ClientToServer::clear_tag8() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.tag8_ = ::int64_t{0}; +} +inline ::int64_t ClientToServer::tag8() const { + // @@protoc_insertion_point(field_get:ClientToServer.tag8) + return _internal_tag8(); +} +inline void ClientToServer::set_tag8(::int64_t value) { + _internal_set_tag8(value); + // @@protoc_insertion_point(field_set:ClientToServer.tag8) +} +inline ::int64_t ClientToServer::_internal_tag8() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.tag8_; +} +inline void ClientToServer::_internal_set_tag8(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.tag8_ = value; +} + +// int64 tag9 = 9; +inline void ClientToServer::clear_tag9() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.tag9_ = ::int64_t{0}; +} +inline ::int64_t ClientToServer::tag9() const { + // @@protoc_insertion_point(field_get:ClientToServer.tag9) + return _internal_tag9(); +} +inline void ClientToServer::set_tag9(::int64_t value) { + _internal_set_tag9(value); + // @@protoc_insertion_point(field_set:ClientToServer.tag9) +} +inline ::int64_t ClientToServer::_internal_tag9() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.tag9_; +} +inline void ClientToServer::_internal_set_tag9(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.tag9_ = value; +} + +// int64 last_update = 10; +inline void ClientToServer::clear_last_update() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.last_update_ = ::int64_t{0}; +} +inline ::int64_t ClientToServer::last_update() const { + // @@protoc_insertion_point(field_get:ClientToServer.last_update) + return _internal_last_update(); +} +inline void ClientToServer::set_last_update(::int64_t value) { + _internal_set_last_update(value); + // @@protoc_insertion_point(field_set:ClientToServer.last_update) +} +inline ::int64_t ClientToServer::_internal_last_update() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.last_update_; +} +inline void ClientToServer::_internal_set_last_update(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.last_update_ = value; +} + +// int64 tag11 = 11; +inline void ClientToServer::clear_tag11() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.tag11_ = ::int64_t{0}; +} +inline ::int64_t ClientToServer::tag11() const { + // @@protoc_insertion_point(field_get:ClientToServer.tag11) + return _internal_tag11(); +} +inline void ClientToServer::set_tag11(::int64_t value) { + _internal_set_tag11(value); + // @@protoc_insertion_point(field_set:ClientToServer.tag11) +} +inline ::int64_t ClientToServer::_internal_tag11() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.tag11_; +} +inline void ClientToServer::_internal_set_tag11(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.tag11_ = value; +} + +// int64 last_player_update = 12; +inline void ClientToServer::clear_last_player_update() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.last_player_update_ = ::int64_t{0}; +} +inline ::int64_t ClientToServer::last_player_update() const { + // @@protoc_insertion_point(field_get:ClientToServer.last_player_update) + return _internal_last_player_update(); +} +inline void ClientToServer::set_last_player_update(::int64_t value) { + _internal_set_last_player_update(value); + // @@protoc_insertion_point(field_set:ClientToServer.last_player_update) +} +inline ::int64_t ClientToServer::_internal_last_player_update() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.last_player_update_; +} +inline void ClientToServer::_internal_set_last_player_update(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.last_player_update_ = value; +} + +// ------------------------------------------------------------------- + +// SegmentResult + +// int64 id = 1; +inline void SegmentResult::clear_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.id_ = ::int64_t{0}; +} +inline ::int64_t SegmentResult::id() const { + // @@protoc_insertion_point(field_get:SegmentResult.id) + return _internal_id(); +} +inline void SegmentResult::set_id(::int64_t value) { + _internal_set_id(value); + // @@protoc_insertion_point(field_set:SegmentResult.id) +} +inline ::int64_t SegmentResult::_internal_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.id_; +} +inline void SegmentResult::_internal_set_id(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.id_ = value; +} + +// int64 rider_id = 2; +inline void SegmentResult::clear_rider_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.rider_id_ = ::int64_t{0}; +} +inline ::int64_t SegmentResult::rider_id() const { + // @@protoc_insertion_point(field_get:SegmentResult.rider_id) + return _internal_rider_id(); +} +inline void SegmentResult::set_rider_id(::int64_t value) { + _internal_set_rider_id(value); + // @@protoc_insertion_point(field_set:SegmentResult.rider_id) +} +inline ::int64_t SegmentResult::_internal_rider_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.rider_id_; +} +inline void SegmentResult::_internal_set_rider_id(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.rider_id_ = value; +} + +// int64 event_subgroup_id = 6; +inline void SegmentResult::clear_event_subgroup_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.event_subgroup_id_ = ::int64_t{0}; +} +inline ::int64_t SegmentResult::event_subgroup_id() const { + // @@protoc_insertion_point(field_get:SegmentResult.event_subgroup_id) + return _internal_event_subgroup_id(); +} +inline void SegmentResult::set_event_subgroup_id(::int64_t value) { + _internal_set_event_subgroup_id(value); + // @@protoc_insertion_point(field_set:SegmentResult.event_subgroup_id) +} +inline ::int64_t SegmentResult::_internal_event_subgroup_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.event_subgroup_id_; +} +inline void SegmentResult::_internal_set_event_subgroup_id(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.event_subgroup_id_ = value; +} + +// string first_name = 7; +inline void SegmentResult::clear_first_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.first_name_.ClearToEmpty(); +} +inline const std::string& SegmentResult::first_name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:SegmentResult.first_name) + return _internal_first_name(); +} +template +inline PROTOBUF_ALWAYS_INLINE void SegmentResult::set_first_name(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.first_name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:SegmentResult.first_name) +} +inline std::string* SegmentResult::mutable_first_name() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_first_name(); + // @@protoc_insertion_point(field_mutable:SegmentResult.first_name) + return _s; +} +inline const std::string& SegmentResult::_internal_first_name() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.first_name_.Get(); +} +inline void SegmentResult::_internal_set_first_name(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.first_name_.Set(value, GetArena()); +} +inline std::string* SegmentResult::_internal_mutable_first_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.first_name_.Mutable( GetArena()); +} +inline std::string* SegmentResult::release_first_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:SegmentResult.first_name) + return _impl_.first_name_.Release(); +} +inline void SegmentResult::set_allocated_first_name(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.first_name_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.first_name_.IsDefault()) { + _impl_.first_name_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:SegmentResult.first_name) +} + +// string last_name = 8; +inline void SegmentResult::clear_last_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.last_name_.ClearToEmpty(); +} +inline const std::string& SegmentResult::last_name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:SegmentResult.last_name) + return _internal_last_name(); +} +template +inline PROTOBUF_ALWAYS_INLINE void SegmentResult::set_last_name(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.last_name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:SegmentResult.last_name) +} +inline std::string* SegmentResult::mutable_last_name() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_last_name(); + // @@protoc_insertion_point(field_mutable:SegmentResult.last_name) + return _s; +} +inline const std::string& SegmentResult::_internal_last_name() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.last_name_.Get(); +} +inline void SegmentResult::_internal_set_last_name(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.last_name_.Set(value, GetArena()); +} +inline std::string* SegmentResult::_internal_mutable_last_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.last_name_.Mutable( GetArena()); +} +inline std::string* SegmentResult::release_last_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:SegmentResult.last_name) + return _impl_.last_name_.Release(); +} +inline void SegmentResult::set_allocated_last_name(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.last_name_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.last_name_.IsDefault()) { + _impl_.last_name_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:SegmentResult.last_name) +} + +// string finish_time_str = 10; +inline void SegmentResult::clear_finish_time_str() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.finish_time_str_.ClearToEmpty(); +} +inline const std::string& SegmentResult::finish_time_str() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:SegmentResult.finish_time_str) + return _internal_finish_time_str(); +} +template +inline PROTOBUF_ALWAYS_INLINE void SegmentResult::set_finish_time_str(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.finish_time_str_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:SegmentResult.finish_time_str) +} +inline std::string* SegmentResult::mutable_finish_time_str() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_finish_time_str(); + // @@protoc_insertion_point(field_mutable:SegmentResult.finish_time_str) + return _s; +} +inline const std::string& SegmentResult::_internal_finish_time_str() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.finish_time_str_.Get(); +} +inline void SegmentResult::_internal_set_finish_time_str(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.finish_time_str_.Set(value, GetArena()); +} +inline std::string* SegmentResult::_internal_mutable_finish_time_str() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.finish_time_str_.Mutable( GetArena()); +} +inline std::string* SegmentResult::release_finish_time_str() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:SegmentResult.finish_time_str) + return _impl_.finish_time_str_.Release(); +} +inline void SegmentResult::set_allocated_finish_time_str(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.finish_time_str_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.finish_time_str_.IsDefault()) { + _impl_.finish_time_str_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:SegmentResult.finish_time_str) +} + +// int64 elapsed_ms = 11; +inline void SegmentResult::clear_elapsed_ms() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.elapsed_ms_ = ::int64_t{0}; +} +inline ::int64_t SegmentResult::elapsed_ms() const { + // @@protoc_insertion_point(field_get:SegmentResult.elapsed_ms) + return _internal_elapsed_ms(); +} +inline void SegmentResult::set_elapsed_ms(::int64_t value) { + _internal_set_elapsed_ms(value); + // @@protoc_insertion_point(field_set:SegmentResult.elapsed_ms) +} +inline ::int64_t SegmentResult::_internal_elapsed_ms() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.elapsed_ms_; +} +inline void SegmentResult::_internal_set_elapsed_ms(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.elapsed_ms_ = value; +} + +// int32 powermeter = 12; +inline void SegmentResult::clear_powermeter() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.powermeter_ = 0; +} +inline ::int32_t SegmentResult::powermeter() const { + // @@protoc_insertion_point(field_get:SegmentResult.powermeter) + return _internal_powermeter(); +} +inline void SegmentResult::set_powermeter(::int32_t value) { + _internal_set_powermeter(value); + // @@protoc_insertion_point(field_set:SegmentResult.powermeter) +} +inline ::int32_t SegmentResult::_internal_powermeter() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.powermeter_; +} +inline void SegmentResult::_internal_set_powermeter(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.powermeter_ = value; +} + +// int32 weight = 13; +inline void SegmentResult::clear_weight() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.weight_ = 0; +} +inline ::int32_t SegmentResult::weight() const { + // @@protoc_insertion_point(field_get:SegmentResult.weight) + return _internal_weight(); +} +inline void SegmentResult::set_weight(::int32_t value) { + _internal_set_weight(value); + // @@protoc_insertion_point(field_set:SegmentResult.weight) +} +inline ::int32_t SegmentResult::_internal_weight() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.weight_; +} +inline void SegmentResult::_internal_set_weight(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.weight_ = value; +} + +// int32 power = 15; +inline void SegmentResult::clear_power() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.power_ = 0; +} +inline ::int32_t SegmentResult::power() const { + // @@protoc_insertion_point(field_get:SegmentResult.power) + return _internal_power(); +} +inline void SegmentResult::set_power(::int32_t value) { + _internal_set_power(value); + // @@protoc_insertion_point(field_set:SegmentResult.power) +} +inline ::int32_t SegmentResult::_internal_power() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.power_; +} +inline void SegmentResult::_internal_set_power(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.power_ = value; +} + +// int32 heartrate = 19; +inline void SegmentResult::clear_heartrate() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.heartrate_ = 0; +} +inline ::int32_t SegmentResult::heartrate() const { + // @@protoc_insertion_point(field_get:SegmentResult.heartrate) + return _internal_heartrate(); +} +inline void SegmentResult::set_heartrate(::int32_t value) { + _internal_set_heartrate(value); + // @@protoc_insertion_point(field_set:SegmentResult.heartrate) +} +inline ::int32_t SegmentResult::_internal_heartrate() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.heartrate_; +} +inline void SegmentResult::_internal_set_heartrate(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.heartrate_ = value; +} + +// ------------------------------------------------------------------- + +// SegmentResults + +// int64 world_id = 1; +inline void SegmentResults::clear_world_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.world_id_ = ::int64_t{0}; +} +inline ::int64_t SegmentResults::world_id() const { + // @@protoc_insertion_point(field_get:SegmentResults.world_id) + return _internal_world_id(); +} +inline void SegmentResults::set_world_id(::int64_t value) { + _internal_set_world_id(value); + // @@protoc_insertion_point(field_set:SegmentResults.world_id) +} +inline ::int64_t SegmentResults::_internal_world_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.world_id_; +} +inline void SegmentResults::_internal_set_world_id(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.world_id_ = value; +} + +// int64 segment_id = 2; +inline void SegmentResults::clear_segment_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.segment_id_ = ::int64_t{0}; +} +inline ::int64_t SegmentResults::segment_id() const { + // @@protoc_insertion_point(field_get:SegmentResults.segment_id) + return _internal_segment_id(); +} +inline void SegmentResults::set_segment_id(::int64_t value) { + _internal_set_segment_id(value); + // @@protoc_insertion_point(field_set:SegmentResults.segment_id) +} +inline ::int64_t SegmentResults::_internal_segment_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.segment_id_; +} +inline void SegmentResults::_internal_set_segment_id(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.segment_id_ = value; +} + +// int64 event_subgroup_id = 3; +inline void SegmentResults::clear_event_subgroup_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.event_subgroup_id_ = ::int64_t{0}; +} +inline ::int64_t SegmentResults::event_subgroup_id() const { + // @@protoc_insertion_point(field_get:SegmentResults.event_subgroup_id) + return _internal_event_subgroup_id(); +} +inline void SegmentResults::set_event_subgroup_id(::int64_t value) { + _internal_set_event_subgroup_id(value); + // @@protoc_insertion_point(field_set:SegmentResults.event_subgroup_id) +} +inline ::int64_t SegmentResults::_internal_event_subgroup_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.event_subgroup_id_; +} +inline void SegmentResults::_internal_set_event_subgroup_id(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.event_subgroup_id_ = value; +} + +// repeated .SegmentResult segment_results = 4; +inline int SegmentResults::_internal_segment_results_size() const { + return _internal_segment_results().size(); +} +inline int SegmentResults::segment_results_size() const { + return _internal_segment_results_size(); +} +inline void SegmentResults::clear_segment_results() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.segment_results_.Clear(); +} +inline ::SegmentResult* SegmentResults::mutable_segment_results(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:SegmentResults.segment_results) + return _internal_mutable_segment_results()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::SegmentResult>* SegmentResults::mutable_segment_results() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:SegmentResults.segment_results) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + return _internal_mutable_segment_results(); +} +inline const ::SegmentResult& SegmentResults::segment_results(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:SegmentResults.segment_results) + return _internal_segment_results().Get(index); +} +inline ::SegmentResult* SegmentResults::add_segment_results() ABSL_ATTRIBUTE_LIFETIME_BOUND { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::SegmentResult* _add = _internal_mutable_segment_results()->Add(); + // @@protoc_insertion_point(field_add:SegmentResults.segment_results) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::SegmentResult>& SegmentResults::segment_results() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:SegmentResults.segment_results) + return _internal_segment_results(); +} +inline const ::google::protobuf::RepeatedPtrField<::SegmentResult>& +SegmentResults::_internal_segment_results() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.segment_results_; +} +inline ::google::protobuf::RepeatedPtrField<::SegmentResult>* +SegmentResults::_internal_mutable_segment_results() { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return &_impl_.segment_results_; +} + +// ------------------------------------------------------------------- + +// UnknownMessage1 + +// ------------------------------------------------------------------- + +// UnknownMessage + +// ------------------------------------------------------------------- + +// ServerToClient + +// int32 tag1 = 1; +inline void ServerToClient::clear_tag1() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.tag1_ = 0; +} +inline ::int32_t ServerToClient::tag1() const { + // @@protoc_insertion_point(field_get:ServerToClient.tag1) + return _internal_tag1(); +} +inline void ServerToClient::set_tag1(::int32_t value) { + _internal_set_tag1(value); + // @@protoc_insertion_point(field_set:ServerToClient.tag1) +} +inline ::int32_t ServerToClient::_internal_tag1() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.tag1_; +} +inline void ServerToClient::_internal_set_tag1(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.tag1_ = value; +} + +// int32 rider_id = 2; +inline void ServerToClient::clear_rider_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.rider_id_ = 0; +} +inline ::int32_t ServerToClient::rider_id() const { + // @@protoc_insertion_point(field_get:ServerToClient.rider_id) + return _internal_rider_id(); +} +inline void ServerToClient::set_rider_id(::int32_t value) { + _internal_set_rider_id(value); + // @@protoc_insertion_point(field_set:ServerToClient.rider_id) +} +inline ::int32_t ServerToClient::_internal_rider_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.rider_id_; +} +inline void ServerToClient::_internal_set_rider_id(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.rider_id_ = value; +} + +// int64 world_time = 3; +inline void ServerToClient::clear_world_time() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.world_time_ = ::int64_t{0}; +} +inline ::int64_t ServerToClient::world_time() const { + // @@protoc_insertion_point(field_get:ServerToClient.world_time) + return _internal_world_time(); +} +inline void ServerToClient::set_world_time(::int64_t value) { + _internal_set_world_time(value); + // @@protoc_insertion_point(field_set:ServerToClient.world_time) +} +inline ::int64_t ServerToClient::_internal_world_time() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.world_time_; +} +inline void ServerToClient::_internal_set_world_time(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.world_time_ = value; +} + +// int32 seqno = 4; +inline void ServerToClient::clear_seqno() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.seqno_ = 0; +} +inline ::int32_t ServerToClient::seqno() const { + // @@protoc_insertion_point(field_get:ServerToClient.seqno) + return _internal_seqno(); +} +inline void ServerToClient::set_seqno(::int32_t value) { + _internal_set_seqno(value); + // @@protoc_insertion_point(field_set:ServerToClient.seqno) +} +inline ::int32_t ServerToClient::_internal_seqno() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.seqno_; +} +inline void ServerToClient::_internal_set_seqno(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.seqno_ = value; +} + +// repeated .PlayerState player_states = 8; +inline int ServerToClient::_internal_player_states_size() const { + return _internal_player_states().size(); +} +inline int ServerToClient::player_states_size() const { + return _internal_player_states_size(); +} +inline void ServerToClient::clear_player_states() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.player_states_.Clear(); +} +inline ::PlayerState* ServerToClient::mutable_player_states(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:ServerToClient.player_states) + return _internal_mutable_player_states()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::PlayerState>* ServerToClient::mutable_player_states() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:ServerToClient.player_states) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + return _internal_mutable_player_states(); +} +inline const ::PlayerState& ServerToClient::player_states(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:ServerToClient.player_states) + return _internal_player_states().Get(index); +} +inline ::PlayerState* ServerToClient::add_player_states() ABSL_ATTRIBUTE_LIFETIME_BOUND { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::PlayerState* _add = _internal_mutable_player_states()->Add(); + // @@protoc_insertion_point(field_add:ServerToClient.player_states) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::PlayerState>& ServerToClient::player_states() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:ServerToClient.player_states) + return _internal_player_states(); +} +inline const ::google::protobuf::RepeatedPtrField<::PlayerState>& +ServerToClient::_internal_player_states() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.player_states_; +} +inline ::google::protobuf::RepeatedPtrField<::PlayerState>* +ServerToClient::_internal_mutable_player_states() { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return &_impl_.player_states_; +} + +// repeated .UnknownMessage player_updates = 9; +inline int ServerToClient::_internal_player_updates_size() const { + return _internal_player_updates().size(); +} +inline int ServerToClient::player_updates_size() const { + return _internal_player_updates_size(); +} +inline void ServerToClient::clear_player_updates() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.player_updates_.Clear(); +} +inline ::UnknownMessage* ServerToClient::mutable_player_updates(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:ServerToClient.player_updates) + return _internal_mutable_player_updates()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::UnknownMessage>* ServerToClient::mutable_player_updates() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:ServerToClient.player_updates) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + return _internal_mutable_player_updates(); +} +inline const ::UnknownMessage& ServerToClient::player_updates(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:ServerToClient.player_updates) + return _internal_player_updates().Get(index); +} +inline ::UnknownMessage* ServerToClient::add_player_updates() ABSL_ATTRIBUTE_LIFETIME_BOUND { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::UnknownMessage* _add = _internal_mutable_player_updates()->Add(); + // @@protoc_insertion_point(field_add:ServerToClient.player_updates) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::UnknownMessage>& ServerToClient::player_updates() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:ServerToClient.player_updates) + return _internal_player_updates(); +} +inline const ::google::protobuf::RepeatedPtrField<::UnknownMessage>& +ServerToClient::_internal_player_updates() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.player_updates_; +} +inline ::google::protobuf::RepeatedPtrField<::UnknownMessage>* +ServerToClient::_internal_mutable_player_updates() { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return &_impl_.player_updates_; +} + +// int64 tag11 = 11; +inline void ServerToClient::clear_tag11() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.tag11_ = ::int64_t{0}; +} +inline ::int64_t ServerToClient::tag11() const { + // @@protoc_insertion_point(field_get:ServerToClient.tag11) + return _internal_tag11(); +} +inline void ServerToClient::set_tag11(::int64_t value) { + _internal_set_tag11(value); + // @@protoc_insertion_point(field_set:ServerToClient.tag11) +} +inline ::int64_t ServerToClient::_internal_tag11() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.tag11_; +} +inline void ServerToClient::_internal_set_tag11(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.tag11_ = value; +} + +// int64 tag17 = 17; +inline void ServerToClient::clear_tag17() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.tag17_ = ::int64_t{0}; +} +inline ::int64_t ServerToClient::tag17() const { + // @@protoc_insertion_point(field_get:ServerToClient.tag17) + return _internal_tag17(); +} +inline void ServerToClient::set_tag17(::int64_t value) { + _internal_set_tag17(value); + // @@protoc_insertion_point(field_set:ServerToClient.tag17) +} +inline ::int64_t ServerToClient::_internal_tag17() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.tag17_; +} +inline void ServerToClient::_internal_set_tag17(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.tag17_ = value; +} + +// int32 num_msgs = 18; +inline void ServerToClient::clear_num_msgs() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.num_msgs_ = 0; +} +inline ::int32_t ServerToClient::num_msgs() const { + // @@protoc_insertion_point(field_get:ServerToClient.num_msgs) + return _internal_num_msgs(); +} +inline void ServerToClient::set_num_msgs(::int32_t value) { + _internal_set_num_msgs(value); + // @@protoc_insertion_point(field_set:ServerToClient.num_msgs) +} +inline ::int32_t ServerToClient::_internal_num_msgs() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.num_msgs_; +} +inline void ServerToClient::_internal_set_num_msgs(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.num_msgs_ = value; +} + +// int32 msgnum = 19; +inline void ServerToClient::clear_msgnum() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.msgnum_ = 0; +} +inline ::int32_t ServerToClient::msgnum() const { + // @@protoc_insertion_point(field_get:ServerToClient.msgnum) + return _internal_msgnum(); +} +inline void ServerToClient::set_msgnum(::int32_t value) { + _internal_set_msgnum(value); + // @@protoc_insertion_point(field_set:ServerToClient.msgnum) +} +inline ::int32_t ServerToClient::_internal_msgnum() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.msgnum_; +} +inline void ServerToClient::_internal_set_msgnum(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.msgnum_ = value; +} + +// ------------------------------------------------------------------- + +// WorldAttributes + +// int32 world_id = 1; +inline void WorldAttributes::clear_world_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.world_id_ = 0; +} +inline ::int32_t WorldAttributes::world_id() const { + // @@protoc_insertion_point(field_get:WorldAttributes.world_id) + return _internal_world_id(); +} +inline void WorldAttributes::set_world_id(::int32_t value) { + _internal_set_world_id(value); + // @@protoc_insertion_point(field_set:WorldAttributes.world_id) +} +inline ::int32_t WorldAttributes::_internal_world_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.world_id_; +} +inline void WorldAttributes::_internal_set_world_id(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.world_id_ = value; +} + +// string name = 2; +inline void WorldAttributes::clear_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.name_.ClearToEmpty(); +} +inline const std::string& WorldAttributes::name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:WorldAttributes.name) + return _internal_name(); +} +template +inline PROTOBUF_ALWAYS_INLINE void WorldAttributes::set_name(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:WorldAttributes.name) +} +inline std::string* WorldAttributes::mutable_name() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:WorldAttributes.name) + return _s; +} +inline const std::string& WorldAttributes::_internal_name() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.name_.Get(); +} +inline void WorldAttributes::_internal_set_name(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.name_.Set(value, GetArena()); +} +inline std::string* WorldAttributes::_internal_mutable_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.name_.Mutable( GetArena()); +} +inline std::string* WorldAttributes::release_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:WorldAttributes.name) + return _impl_.name_.Release(); +} +inline void WorldAttributes::set_allocated_name(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.name_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:WorldAttributes.name) +} + +// int64 tag3 = 3; +inline void WorldAttributes::clear_tag3() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.tag3_ = ::int64_t{0}; +} +inline ::int64_t WorldAttributes::tag3() const { + // @@protoc_insertion_point(field_get:WorldAttributes.tag3) + return _internal_tag3(); +} +inline void WorldAttributes::set_tag3(::int64_t value) { + _internal_set_tag3(value); + // @@protoc_insertion_point(field_set:WorldAttributes.tag3) +} +inline ::int64_t WorldAttributes::_internal_tag3() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.tag3_; +} +inline void WorldAttributes::_internal_set_tag3(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.tag3_ = value; +} + +// int64 tag5 = 4; +inline void WorldAttributes::clear_tag5() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.tag5_ = ::int64_t{0}; +} +inline ::int64_t WorldAttributes::tag5() const { + // @@protoc_insertion_point(field_get:WorldAttributes.tag5) + return _internal_tag5(); +} +inline void WorldAttributes::set_tag5(::int64_t value) { + _internal_set_tag5(value); + // @@protoc_insertion_point(field_set:WorldAttributes.tag5) +} +inline ::int64_t WorldAttributes::_internal_tag5() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.tag5_; +} +inline void WorldAttributes::_internal_set_tag5(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.tag5_ = value; +} + +// int64 world_time = 6; +inline void WorldAttributes::clear_world_time() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.world_time_ = ::int64_t{0}; +} +inline ::int64_t WorldAttributes::world_time() const { + // @@protoc_insertion_point(field_get:WorldAttributes.world_time) + return _internal_world_time(); +} +inline void WorldAttributes::set_world_time(::int64_t value) { + _internal_set_world_time(value); + // @@protoc_insertion_point(field_set:WorldAttributes.world_time) +} +inline ::int64_t WorldAttributes::_internal_world_time() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.world_time_; +} +inline void WorldAttributes::_internal_set_world_time(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.world_time_ = value; +} + +// int64 clock_time = 7; +inline void WorldAttributes::clear_clock_time() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.clock_time_ = ::int64_t{0}; +} +inline ::int64_t WorldAttributes::clock_time() const { + // @@protoc_insertion_point(field_get:WorldAttributes.clock_time) + return _internal_clock_time(); +} +inline void WorldAttributes::set_clock_time(::int64_t value) { + _internal_set_clock_time(value); + // @@protoc_insertion_point(field_set:WorldAttributes.clock_time) +} +inline ::int64_t WorldAttributes::_internal_clock_time() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.clock_time_; +} +inline void WorldAttributes::_internal_set_clock_time(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.clock_time_ = value; +} + +// ------------------------------------------------------------------- + +// WorldAttribute + +// int64 world_time = 2; +inline void WorldAttribute::clear_world_time() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.world_time_ = ::int64_t{0}; +} +inline ::int64_t WorldAttribute::world_time() const { + // @@protoc_insertion_point(field_get:WorldAttribute.world_time) + return _internal_world_time(); +} +inline void WorldAttribute::set_world_time(::int64_t value) { + _internal_set_world_time(value); + // @@protoc_insertion_point(field_set:WorldAttribute.world_time) +} +inline ::int64_t WorldAttribute::_internal_world_time() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.world_time_; +} +inline void WorldAttribute::_internal_set_world_time(::int64_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.world_time_ = value; +} + +// ------------------------------------------------------------------- + +// EventSubgroupProtobuf + +// int32 id = 1; +inline void EventSubgroupProtobuf::clear_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.id_ = 0; +} +inline ::int32_t EventSubgroupProtobuf::id() const { + // @@protoc_insertion_point(field_get:EventSubgroupProtobuf.id) + return _internal_id(); +} +inline void EventSubgroupProtobuf::set_id(::int32_t value) { + _internal_set_id(value); + // @@protoc_insertion_point(field_set:EventSubgroupProtobuf.id) +} +inline ::int32_t EventSubgroupProtobuf::_internal_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.id_; +} +inline void EventSubgroupProtobuf::_internal_set_id(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.id_ = value; +} + +// string name = 2; +inline void EventSubgroupProtobuf::clear_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.name_.ClearToEmpty(); +} +inline const std::string& EventSubgroupProtobuf::name() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:EventSubgroupProtobuf.name) + return _internal_name(); +} +template +inline PROTOBUF_ALWAYS_INLINE void EventSubgroupProtobuf::set_name(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.name_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:EventSubgroupProtobuf.name) +} +inline std::string* EventSubgroupProtobuf::mutable_name() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:EventSubgroupProtobuf.name) + return _s; +} +inline const std::string& EventSubgroupProtobuf::_internal_name() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.name_.Get(); +} +inline void EventSubgroupProtobuf::_internal_set_name(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.name_.Set(value, GetArena()); +} +inline std::string* EventSubgroupProtobuf::_internal_mutable_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.name_.Mutable( GetArena()); +} +inline std::string* EventSubgroupProtobuf::release_name() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:EventSubgroupProtobuf.name) + return _impl_.name_.Release(); +} +inline void EventSubgroupProtobuf::set_allocated_name(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.name_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:EventSubgroupProtobuf.name) +} + +// int32 rules = 8; +inline void EventSubgroupProtobuf::clear_rules() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.rules_ = 0; +} +inline ::int32_t EventSubgroupProtobuf::rules() const { + // @@protoc_insertion_point(field_get:EventSubgroupProtobuf.rules) + return _internal_rules(); +} +inline void EventSubgroupProtobuf::set_rules(::int32_t value) { + _internal_set_rules(value); + // @@protoc_insertion_point(field_set:EventSubgroupProtobuf.rules) +} +inline ::int32_t EventSubgroupProtobuf::_internal_rules() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.rules_; +} +inline void EventSubgroupProtobuf::_internal_set_rules(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.rules_ = value; +} + +// int32 route = 22; +inline void EventSubgroupProtobuf::clear_route() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.route_ = 0; +} +inline ::int32_t EventSubgroupProtobuf::route() const { + // @@protoc_insertion_point(field_get:EventSubgroupProtobuf.route) + return _internal_route(); +} +inline void EventSubgroupProtobuf::set_route(::int32_t value) { + _internal_set_route(value); + // @@protoc_insertion_point(field_set:EventSubgroupProtobuf.route) +} +inline ::int32_t EventSubgroupProtobuf::_internal_route() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.route_; +} +inline void EventSubgroupProtobuf::_internal_set_route(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.route_ = value; +} + +// int32 laps = 25; +inline void EventSubgroupProtobuf::clear_laps() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.laps_ = 0; +} +inline ::int32_t EventSubgroupProtobuf::laps() const { + // @@protoc_insertion_point(field_get:EventSubgroupProtobuf.laps) + return _internal_laps(); +} +inline void EventSubgroupProtobuf::set_laps(::int32_t value) { + _internal_set_laps(value); + // @@protoc_insertion_point(field_set:EventSubgroupProtobuf.laps) +} +inline ::int32_t EventSubgroupProtobuf::_internal_laps() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.laps_; +} +inline void EventSubgroupProtobuf::_internal_set_laps(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.laps_ = value; +} + +// int32 startLocation = 29; +inline void EventSubgroupProtobuf::clear_startlocation() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.startlocation_ = 0; +} +inline ::int32_t EventSubgroupProtobuf::startlocation() const { + // @@protoc_insertion_point(field_get:EventSubgroupProtobuf.startLocation) + return _internal_startlocation(); +} +inline void EventSubgroupProtobuf::set_startlocation(::int32_t value) { + _internal_set_startlocation(value); + // @@protoc_insertion_point(field_set:EventSubgroupProtobuf.startLocation) +} +inline ::int32_t EventSubgroupProtobuf::_internal_startlocation() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.startlocation_; +} +inline void EventSubgroupProtobuf::_internal_set_startlocation(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.startlocation_ = value; +} + +// int32 label = 30; +inline void EventSubgroupProtobuf::clear_label() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.label_ = 0; +} +inline ::int32_t EventSubgroupProtobuf::label() const { + // @@protoc_insertion_point(field_get:EventSubgroupProtobuf.label) + return _internal_label(); +} +inline void EventSubgroupProtobuf::set_label(::int32_t value) { + _internal_set_label(value); + // @@protoc_insertion_point(field_set:EventSubgroupProtobuf.label) +} +inline ::int32_t EventSubgroupProtobuf::_internal_label() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.label_; +} +inline void EventSubgroupProtobuf::_internal_set_label(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.label_ = value; +} + +// int32 paceType = 31; +inline void EventSubgroupProtobuf::clear_pacetype() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.pacetype_ = 0; +} +inline ::int32_t EventSubgroupProtobuf::pacetype() const { + // @@protoc_insertion_point(field_get:EventSubgroupProtobuf.paceType) + return _internal_pacetype(); +} +inline void EventSubgroupProtobuf::set_pacetype(::int32_t value) { + _internal_set_pacetype(value); + // @@protoc_insertion_point(field_set:EventSubgroupProtobuf.paceType) +} +inline ::int32_t EventSubgroupProtobuf::_internal_pacetype() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.pacetype_; +} +inline void EventSubgroupProtobuf::_internal_set_pacetype(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.pacetype_ = value; +} + +// int32 jerseyHash = 36; +inline void EventSubgroupProtobuf::clear_jerseyhash() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.jerseyhash_ = 0; +} +inline ::int32_t EventSubgroupProtobuf::jerseyhash() const { + // @@protoc_insertion_point(field_get:EventSubgroupProtobuf.jerseyHash) + return _internal_jerseyhash(); +} +inline void EventSubgroupProtobuf::set_jerseyhash(::int32_t value) { + _internal_set_jerseyhash(value); + // @@protoc_insertion_point(field_set:EventSubgroupProtobuf.jerseyHash) +} +inline ::int32_t EventSubgroupProtobuf::_internal_jerseyhash() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.jerseyhash_; +} +inline void EventSubgroupProtobuf::_internal_set_jerseyhash(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.jerseyhash_ = value; +} + +// ------------------------------------------------------------------- + +// RiderAttributes_AttributeMessage + +// int32 myId = 1; +inline void RiderAttributes_AttributeMessage::clear_myid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.myid_ = 0; +} +inline ::int32_t RiderAttributes_AttributeMessage::myid() const { + // @@protoc_insertion_point(field_get:RiderAttributes.AttributeMessage.myId) + return _internal_myid(); +} +inline void RiderAttributes_AttributeMessage::set_myid(::int32_t value) { + _internal_set_myid(value); + // @@protoc_insertion_point(field_set:RiderAttributes.AttributeMessage.myId) +} +inline ::int32_t RiderAttributes_AttributeMessage::_internal_myid() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.myid_; +} +inline void RiderAttributes_AttributeMessage::_internal_set_myid(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.myid_ = value; +} + +// int32 theirId = 2; +inline void RiderAttributes_AttributeMessage::clear_theirid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.theirid_ = 0; +} +inline ::int32_t RiderAttributes_AttributeMessage::theirid() const { + // @@protoc_insertion_point(field_get:RiderAttributes.AttributeMessage.theirId) + return _internal_theirid(); +} +inline void RiderAttributes_AttributeMessage::set_theirid(::int32_t value) { + _internal_set_theirid(value); + // @@protoc_insertion_point(field_set:RiderAttributes.AttributeMessage.theirId) +} +inline ::int32_t RiderAttributes_AttributeMessage::_internal_theirid() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.theirid_; +} +inline void RiderAttributes_AttributeMessage::_internal_set_theirid(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.theirid_ = value; +} + +// string firstName = 3; +inline void RiderAttributes_AttributeMessage::clear_firstname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.firstname_.ClearToEmpty(); +} +inline const std::string& RiderAttributes_AttributeMessage::firstname() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:RiderAttributes.AttributeMessage.firstName) + return _internal_firstname(); +} +template +inline PROTOBUF_ALWAYS_INLINE void RiderAttributes_AttributeMessage::set_firstname(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.firstname_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:RiderAttributes.AttributeMessage.firstName) +} +inline std::string* RiderAttributes_AttributeMessage::mutable_firstname() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_firstname(); + // @@protoc_insertion_point(field_mutable:RiderAttributes.AttributeMessage.firstName) + return _s; +} +inline const std::string& RiderAttributes_AttributeMessage::_internal_firstname() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.firstname_.Get(); +} +inline void RiderAttributes_AttributeMessage::_internal_set_firstname(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.firstname_.Set(value, GetArena()); +} +inline std::string* RiderAttributes_AttributeMessage::_internal_mutable_firstname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.firstname_.Mutable( GetArena()); +} +inline std::string* RiderAttributes_AttributeMessage::release_firstname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:RiderAttributes.AttributeMessage.firstName) + return _impl_.firstname_.Release(); +} +inline void RiderAttributes_AttributeMessage::set_allocated_firstname(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.firstname_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.firstname_.IsDefault()) { + _impl_.firstname_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:RiderAttributes.AttributeMessage.firstName) +} + +// string lastName = 4; +inline void RiderAttributes_AttributeMessage::clear_lastname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.lastname_.ClearToEmpty(); +} +inline const std::string& RiderAttributes_AttributeMessage::lastname() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:RiderAttributes.AttributeMessage.lastName) + return _internal_lastname(); +} +template +inline PROTOBUF_ALWAYS_INLINE void RiderAttributes_AttributeMessage::set_lastname(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.lastname_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:RiderAttributes.AttributeMessage.lastName) +} +inline std::string* RiderAttributes_AttributeMessage::mutable_lastname() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_lastname(); + // @@protoc_insertion_point(field_mutable:RiderAttributes.AttributeMessage.lastName) + return _s; +} +inline const std::string& RiderAttributes_AttributeMessage::_internal_lastname() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.lastname_.Get(); +} +inline void RiderAttributes_AttributeMessage::_internal_set_lastname(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.lastname_.Set(value, GetArena()); +} +inline std::string* RiderAttributes_AttributeMessage::_internal_mutable_lastname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.lastname_.Mutable( GetArena()); +} +inline std::string* RiderAttributes_AttributeMessage::release_lastname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:RiderAttributes.AttributeMessage.lastName) + return _impl_.lastname_.Release(); +} +inline void RiderAttributes_AttributeMessage::set_allocated_lastname(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.lastname_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.lastname_.IsDefault()) { + _impl_.lastname_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:RiderAttributes.AttributeMessage.lastName) +} + +// int32 countryCode = 5; +inline void RiderAttributes_AttributeMessage::clear_countrycode() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.countrycode_ = 0; +} +inline ::int32_t RiderAttributes_AttributeMessage::countrycode() const { + // @@protoc_insertion_point(field_get:RiderAttributes.AttributeMessage.countryCode) + return _internal_countrycode(); +} +inline void RiderAttributes_AttributeMessage::set_countrycode(::int32_t value) { + _internal_set_countrycode(value); + // @@protoc_insertion_point(field_set:RiderAttributes.AttributeMessage.countryCode) +} +inline ::int32_t RiderAttributes_AttributeMessage::_internal_countrycode() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.countrycode_; +} +inline void RiderAttributes_AttributeMessage::_internal_set_countrycode(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.countrycode_ = value; +} + +// ------------------------------------------------------------------- + +// RiderAttributes + +// int32 f2 = 2; +inline void RiderAttributes::clear_f2() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.f2_ = 0; +} +inline ::int32_t RiderAttributes::f2() const { + // @@protoc_insertion_point(field_get:RiderAttributes.f2) + return _internal_f2(); +} +inline void RiderAttributes::set_f2(::int32_t value) { + _internal_set_f2(value); + // @@protoc_insertion_point(field_set:RiderAttributes.f2) +} +inline ::int32_t RiderAttributes::_internal_f2() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.f2_; +} +inline void RiderAttributes::_internal_set_f2(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.f2_ = value; +} + +// int32 f3 = 3; +inline void RiderAttributes::clear_f3() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.f3_ = 0; +} +inline ::int32_t RiderAttributes::f3() const { + // @@protoc_insertion_point(field_get:RiderAttributes.f3) + return _internal_f3(); +} +inline void RiderAttributes::set_f3(::int32_t value) { + _internal_set_f3(value); + // @@protoc_insertion_point(field_set:RiderAttributes.f3) +} +inline ::int32_t RiderAttributes::_internal_f3() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.f3_; +} +inline void RiderAttributes::_internal_set_f3(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.f3_ = value; +} + +// .RiderAttributes.AttributeMessage attributeMessage = 4; +inline bool RiderAttributes::has_attributemessage() const { + bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; + PROTOBUF_ASSUME(!value || _impl_.attributemessage_ != nullptr); + return value; +} +inline void RiderAttributes::clear_attributemessage() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (_impl_.attributemessage_ != nullptr) _impl_.attributemessage_->Clear(); + _impl_._has_bits_[0] &= ~0x00000001u; +} +inline const ::RiderAttributes_AttributeMessage& RiderAttributes::_internal_attributemessage() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + const ::RiderAttributes_AttributeMessage* p = _impl_.attributemessage_; + return p != nullptr ? *p : reinterpret_cast(::_RiderAttributes_AttributeMessage_default_instance_); +} +inline const ::RiderAttributes_AttributeMessage& RiderAttributes::attributemessage() const ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:RiderAttributes.attributeMessage) + return _internal_attributemessage(); +} +inline void RiderAttributes::unsafe_arena_set_allocated_attributemessage(::RiderAttributes_AttributeMessage* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (GetArena() == nullptr) { + delete reinterpret_cast<::google::protobuf::MessageLite*>(_impl_.attributemessage_); + } + _impl_.attributemessage_ = reinterpret_cast<::RiderAttributes_AttributeMessage*>(value); + if (value != nullptr) { + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:RiderAttributes.attributeMessage) +} +inline ::RiderAttributes_AttributeMessage* RiderAttributes::release_attributemessage() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + + _impl_._has_bits_[0] &= ~0x00000001u; + ::RiderAttributes_AttributeMessage* released = _impl_.attributemessage_; + _impl_.attributemessage_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::google::protobuf::MessageLite*>(released); + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + if (GetArena() == nullptr) { + delete old; + } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArena() != nullptr) { + released = ::google::protobuf::internal::DuplicateIfNonNull(released); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return released; +} +inline ::RiderAttributes_AttributeMessage* RiderAttributes::unsafe_arena_release_attributemessage() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:RiderAttributes.attributeMessage) + + _impl_._has_bits_[0] &= ~0x00000001u; + ::RiderAttributes_AttributeMessage* temp = _impl_.attributemessage_; + _impl_.attributemessage_ = nullptr; + return temp; +} +inline ::RiderAttributes_AttributeMessage* RiderAttributes::_internal_mutable_attributemessage() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_._has_bits_[0] |= 0x00000001u; + if (_impl_.attributemessage_ == nullptr) { + auto* p = CreateMaybeMessage<::RiderAttributes_AttributeMessage>(GetArena()); + _impl_.attributemessage_ = reinterpret_cast<::RiderAttributes_AttributeMessage*>(p); + } + return _impl_.attributemessage_; +} +inline ::RiderAttributes_AttributeMessage* RiderAttributes::mutable_attributemessage() ABSL_ATTRIBUTE_LIFETIME_BOUND { + ::RiderAttributes_AttributeMessage* _msg = _internal_mutable_attributemessage(); + // @@protoc_insertion_point(field_mutable:RiderAttributes.attributeMessage) + return _msg; +} +inline void RiderAttributes::set_allocated_attributemessage(::RiderAttributes_AttributeMessage* value) { + ::google::protobuf::Arena* message_arena = GetArena(); + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + if (message_arena == nullptr) { + delete reinterpret_cast<::RiderAttributes_AttributeMessage*>(_impl_.attributemessage_); + } + + if (value != nullptr) { + ::google::protobuf::Arena* submessage_arena = reinterpret_cast<::RiderAttributes_AttributeMessage*>(value)->GetArena(); + if (message_arena != submessage_arena) { + value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena); + } + _impl_._has_bits_[0] |= 0x00000001u; + } else { + _impl_._has_bits_[0] &= ~0x00000001u; + } + + _impl_.attributemessage_ = reinterpret_cast<::RiderAttributes_AttributeMessage*>(value); + // @@protoc_insertion_point(field_set_allocated:RiderAttributes.attributeMessage) +} + +// int32 theirId = 10; +inline void RiderAttributes::clear_theirid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.theirid_ = 0; +} +inline ::int32_t RiderAttributes::theirid() const { + // @@protoc_insertion_point(field_get:RiderAttributes.theirId) + return _internal_theirid(); +} +inline void RiderAttributes::set_theirid(::int32_t value) { + _internal_set_theirid(value); + // @@protoc_insertion_point(field_set:RiderAttributes.theirId) +} +inline ::int32_t RiderAttributes::_internal_theirid() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.theirid_; +} +inline void RiderAttributes::_internal_set_theirid(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.theirid_ = value; +} + +// int32 f13 = 13; +inline void RiderAttributes::clear_f13() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.f13_ = 0; +} +inline ::int32_t RiderAttributes::f13() const { + // @@protoc_insertion_point(field_get:RiderAttributes.f13) + return _internal_f13(); +} +inline void RiderAttributes::set_f13(::int32_t value) { + _internal_set_f13(value); + // @@protoc_insertion_point(field_set:RiderAttributes.f13) +} +inline ::int32_t RiderAttributes::_internal_f13() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.f13_; +} +inline void RiderAttributes::_internal_set_f13(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.f13_ = value; +} + +// ------------------------------------------------------------------- + +// Profiles + +// repeated .Profile profiles = 1; +inline int Profiles::_internal_profiles_size() const { + return _internal_profiles().size(); +} +inline int Profiles::profiles_size() const { + return _internal_profiles_size(); +} +inline void Profiles::clear_profiles() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.profiles_.Clear(); +} +inline ::Profile* Profiles::mutable_profiles(int index) + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable:Profiles.profiles) + return _internal_mutable_profiles()->Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField<::Profile>* Profiles::mutable_profiles() + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_mutable_list:Profiles.profiles) + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + return _internal_mutable_profiles(); +} +inline const ::Profile& Profiles::profiles(int index) const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:Profiles.profiles) + return _internal_profiles().Get(index); +} +inline ::Profile* Profiles::add_profiles() ABSL_ATTRIBUTE_LIFETIME_BOUND { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ::Profile* _add = _internal_mutable_profiles()->Add(); + // @@protoc_insertion_point(field_add:Profiles.profiles) + return _add; +} +inline const ::google::protobuf::RepeatedPtrField<::Profile>& Profiles::profiles() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_list:Profiles.profiles) + return _internal_profiles(); +} +inline const ::google::protobuf::RepeatedPtrField<::Profile>& +Profiles::_internal_profiles() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.profiles_; +} +inline ::google::protobuf::RepeatedPtrField<::Profile>* +Profiles::_internal_mutable_profiles() { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return &_impl_.profiles_; +} + +// ------------------------------------------------------------------- + +// Profile + +// int32 id = 1; +inline void Profile::clear_id() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.id_ = 0; +} +inline ::int32_t Profile::id() const { + // @@protoc_insertion_point(field_get:Profile.id) + return _internal_id(); +} +inline void Profile::set_id(::int32_t value) { + _internal_set_id(value); + // @@protoc_insertion_point(field_set:Profile.id) +} +inline ::int32_t Profile::_internal_id() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.id_; +} +inline void Profile::_internal_set_id(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.id_ = value; +} + +// string firstName = 4; +inline void Profile::clear_firstname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.firstname_.ClearToEmpty(); +} +inline const std::string& Profile::firstname() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:Profile.firstName) + return _internal_firstname(); +} +template +inline PROTOBUF_ALWAYS_INLINE void Profile::set_firstname(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.firstname_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:Profile.firstName) +} +inline std::string* Profile::mutable_firstname() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_firstname(); + // @@protoc_insertion_point(field_mutable:Profile.firstName) + return _s; +} +inline const std::string& Profile::_internal_firstname() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.firstname_.Get(); +} +inline void Profile::_internal_set_firstname(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.firstname_.Set(value, GetArena()); +} +inline std::string* Profile::_internal_mutable_firstname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.firstname_.Mutable( GetArena()); +} +inline std::string* Profile::release_firstname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:Profile.firstName) + return _impl_.firstname_.Release(); +} +inline void Profile::set_allocated_firstname(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.firstname_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.firstname_.IsDefault()) { + _impl_.firstname_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:Profile.firstName) +} + +// string lastName = 5; +inline void Profile::clear_lastname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.lastname_.ClearToEmpty(); +} +inline const std::string& Profile::lastname() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:Profile.lastName) + return _internal_lastname(); +} +template +inline PROTOBUF_ALWAYS_INLINE void Profile::set_lastname(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.lastname_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:Profile.lastName) +} +inline std::string* Profile::mutable_lastname() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_lastname(); + // @@protoc_insertion_point(field_mutable:Profile.lastName) + return _s; +} +inline const std::string& Profile::_internal_lastname() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.lastname_.Get(); +} +inline void Profile::_internal_set_lastname(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.lastname_.Set(value, GetArena()); +} +inline std::string* Profile::_internal_mutable_lastname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.lastname_.Mutable( GetArena()); +} +inline std::string* Profile::release_lastname() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:Profile.lastName) + return _impl_.lastname_.Release(); +} +inline void Profile::set_allocated_lastname(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.lastname_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.lastname_.IsDefault()) { + _impl_.lastname_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:Profile.lastName) +} + +// int32 male = 6; +inline void Profile::clear_male() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.male_ = 0; +} +inline ::int32_t Profile::male() const { + // @@protoc_insertion_point(field_get:Profile.male) + return _internal_male(); +} +inline void Profile::set_male(::int32_t value) { + _internal_set_male(value); + // @@protoc_insertion_point(field_set:Profile.male) +} +inline ::int32_t Profile::_internal_male() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.male_; +} +inline void Profile::_internal_set_male(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.male_ = value; +} + +// int32 weight = 9; +inline void Profile::clear_weight() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.weight_ = 0; +} +inline ::int32_t Profile::weight() const { + // @@protoc_insertion_point(field_get:Profile.weight) + return _internal_weight(); +} +inline void Profile::set_weight(::int32_t value) { + _internal_set_weight(value); + // @@protoc_insertion_point(field_set:Profile.weight) +} +inline ::int32_t Profile::_internal_weight() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.weight_; +} +inline void Profile::_internal_set_weight(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.weight_ = value; +} + +// int32 bodyType = 12; +inline void Profile::clear_bodytype() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.bodytype_ = 0; +} +inline ::int32_t Profile::bodytype() const { + // @@protoc_insertion_point(field_get:Profile.bodyType) + return _internal_bodytype(); +} +inline void Profile::set_bodytype(::int32_t value) { + _internal_set_bodytype(value); + // @@protoc_insertion_point(field_set:Profile.bodyType) +} +inline ::int32_t Profile::_internal_bodytype() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.bodytype_; +} +inline void Profile::_internal_set_bodytype(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.bodytype_ = value; +} + +// int32 countryCode = 34; +inline void Profile::clear_countrycode() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.countrycode_ = 0; +} +inline ::int32_t Profile::countrycode() const { + // @@protoc_insertion_point(field_get:Profile.countryCode) + return _internal_countrycode(); +} +inline void Profile::set_countrycode(::int32_t value) { + _internal_set_countrycode(value); + // @@protoc_insertion_point(field_set:Profile.countryCode) +} +inline ::int32_t Profile::_internal_countrycode() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.countrycode_; +} +inline void Profile::_internal_set_countrycode(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.countrycode_ = value; +} + +// int32 totalDistance = 35; +inline void Profile::clear_totaldistance() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.totaldistance_ = 0; +} +inline ::int32_t Profile::totaldistance() const { + // @@protoc_insertion_point(field_get:Profile.totalDistance) + return _internal_totaldistance(); +} +inline void Profile::set_totaldistance(::int32_t value) { + _internal_set_totaldistance(value); + // @@protoc_insertion_point(field_set:Profile.totalDistance) +} +inline ::int32_t Profile::_internal_totaldistance() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.totaldistance_; +} +inline void Profile::_internal_set_totaldistance(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.totaldistance_ = value; +} + +// int32 totalDistanceClimbed = 36; +inline void Profile::clear_totaldistanceclimbed() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.totaldistanceclimbed_ = 0; +} +inline ::int32_t Profile::totaldistanceclimbed() const { + // @@protoc_insertion_point(field_get:Profile.totalDistanceClimbed) + return _internal_totaldistanceclimbed(); +} +inline void Profile::set_totaldistanceclimbed(::int32_t value) { + _internal_set_totaldistanceclimbed(value); + // @@protoc_insertion_point(field_set:Profile.totalDistanceClimbed) +} +inline ::int32_t Profile::_internal_totaldistanceclimbed() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.totaldistanceclimbed_; +} +inline void Profile::_internal_set_totaldistanceclimbed(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.totaldistanceclimbed_ = value; +} + +// int32 totalTimeInMinutes = 37; +inline void Profile::clear_totaltimeinminutes() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.totaltimeinminutes_ = 0; +} +inline ::int32_t Profile::totaltimeinminutes() const { + // @@protoc_insertion_point(field_get:Profile.totalTimeInMinutes) + return _internal_totaltimeinminutes(); +} +inline void Profile::set_totaltimeinminutes(::int32_t value) { + _internal_set_totaltimeinminutes(value); + // @@protoc_insertion_point(field_set:Profile.totalTimeInMinutes) +} +inline ::int32_t Profile::_internal_totaltimeinminutes() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.totaltimeinminutes_; +} +inline void Profile::_internal_set_totaltimeinminutes(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.totaltimeinminutes_ = value; +} + +// int32 totalWattHours = 41; +inline void Profile::clear_totalwatthours() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.totalwatthours_ = 0; +} +inline ::int32_t Profile::totalwatthours() const { + // @@protoc_insertion_point(field_get:Profile.totalWattHours) + return _internal_totalwatthours(); +} +inline void Profile::set_totalwatthours(::int32_t value) { + _internal_set_totalwatthours(value); + // @@protoc_insertion_point(field_set:Profile.totalWattHours) +} +inline ::int32_t Profile::_internal_totalwatthours() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.totalwatthours_; +} +inline void Profile::_internal_set_totalwatthours(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.totalwatthours_ = value; +} + +// int32 height = 42; +inline void Profile::clear_height() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.height_ = 0; +} +inline ::int32_t Profile::height() const { + // @@protoc_insertion_point(field_get:Profile.height) + return _internal_height(); +} +inline void Profile::set_height(::int32_t value) { + _internal_set_height(value); + // @@protoc_insertion_point(field_set:Profile.height) +} +inline ::int32_t Profile::_internal_height() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.height_; +} +inline void Profile::_internal_set_height(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.height_ = value; +} + +// int32 totalExperiencePoints = 46; +inline void Profile::clear_totalexperiencepoints() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.totalexperiencepoints_ = 0; +} +inline ::int32_t Profile::totalexperiencepoints() const { + // @@protoc_insertion_point(field_get:Profile.totalExperiencePoints) + return _internal_totalexperiencepoints(); +} +inline void Profile::set_totalexperiencepoints(::int32_t value) { + _internal_set_totalexperiencepoints(value); + // @@protoc_insertion_point(field_set:Profile.totalExperiencePoints) +} +inline ::int32_t Profile::_internal_totalexperiencepoints() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.totalexperiencepoints_; +} +inline void Profile::_internal_set_totalexperiencepoints(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.totalexperiencepoints_ = value; +} + +// int32 achievementLevel = 49; +inline void Profile::clear_achievementlevel() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.achievementlevel_ = 0; +} +inline ::int32_t Profile::achievementlevel() const { + // @@protoc_insertion_point(field_get:Profile.achievementLevel) + return _internal_achievementlevel(); +} +inline void Profile::set_achievementlevel(::int32_t value) { + _internal_set_achievementlevel(value); + // @@protoc_insertion_point(field_set:Profile.achievementLevel) +} +inline ::int32_t Profile::_internal_achievementlevel() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.achievementlevel_; +} +inline void Profile::_internal_set_achievementlevel(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.achievementlevel_ = value; +} + +// int32 powerSource = 52; +inline void Profile::clear_powersource() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.powersource_ = 0; +} +inline ::int32_t Profile::powersource() const { + // @@protoc_insertion_point(field_get:Profile.powerSource) + return _internal_powersource(); +} +inline void Profile::set_powersource(::int32_t value) { + _internal_set_powersource(value); + // @@protoc_insertion_point(field_set:Profile.powerSource) +} +inline ::int32_t Profile::_internal_powersource() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.powersource_; +} +inline void Profile::_internal_set_powersource(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.powersource_ = value; +} + +// int32 age = 55; +inline void Profile::clear_age() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.age_ = 0; +} +inline ::int32_t Profile::age() const { + // @@protoc_insertion_point(field_get:Profile.age) + return _internal_age(); +} +inline void Profile::set_age(::int32_t value) { + _internal_set_age(value); + // @@protoc_insertion_point(field_set:Profile.age) +} +inline ::int32_t Profile::_internal_age() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.age_; +} +inline void Profile::_internal_set_age(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.age_ = value; +} + +// string launchedGameClient = 108; +inline void Profile::clear_launchedgameclient() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.launchedgameclient_.ClearToEmpty(); +} +inline const std::string& Profile::launchedgameclient() const + ABSL_ATTRIBUTE_LIFETIME_BOUND { + // @@protoc_insertion_point(field_get:Profile.launchedGameClient) + return _internal_launchedgameclient(); +} +template +inline PROTOBUF_ALWAYS_INLINE void Profile::set_launchedgameclient(Arg_&& arg, + Args_... args) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.launchedgameclient_.Set(static_cast(arg), args..., GetArena()); + // @@protoc_insertion_point(field_set:Profile.launchedGameClient) +} +inline std::string* Profile::mutable_launchedgameclient() ABSL_ATTRIBUTE_LIFETIME_BOUND { + std::string* _s = _internal_mutable_launchedgameclient(); + // @@protoc_insertion_point(field_mutable:Profile.launchedGameClient) + return _s; +} +inline const std::string& Profile::_internal_launchedgameclient() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.launchedgameclient_.Get(); +} +inline void Profile::_internal_set_launchedgameclient(const std::string& value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.launchedgameclient_.Set(value, GetArena()); +} +inline std::string* Profile::_internal_mutable_launchedgameclient() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + return _impl_.launchedgameclient_.Mutable( GetArena()); +} +inline std::string* Profile::release_launchedgameclient() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + // @@protoc_insertion_point(field_release:Profile.launchedGameClient) + return _impl_.launchedgameclient_.Release(); +} +inline void Profile::set_allocated_launchedgameclient(std::string* value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.launchedgameclient_.SetAllocated(value, GetArena()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.launchedgameclient_.IsDefault()) { + _impl_.launchedgameclient_.Set("", GetArena()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:Profile.launchedGameClient) +} + +// int32 currentActivityId = 109; +inline void Profile::clear_currentactivityid() { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + _impl_.currentactivityid_ = 0; +} +inline ::int32_t Profile::currentactivityid() const { + // @@protoc_insertion_point(field_get:Profile.currentActivityId) + return _internal_currentactivityid(); +} +inline void Profile::set_currentactivityid(::int32_t value) { + _internal_set_currentactivityid(value); + // @@protoc_insertion_point(field_set:Profile.currentActivityId) +} +inline ::int32_t Profile::_internal_currentactivityid() const { + PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race); + return _impl_.currentactivityid_; +} +inline void Profile::_internal_set_currentactivityid(::int32_t value) { + PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race); + ; + _impl_.currentactivityid_ = value; +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + + +// @@protoc_insertion_point(global_scope) + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_INCLUDED_zwift_5fmessages_2eproto_2epb_2eh diff --git a/src/zwift-api/zwift_messages.pb.swift b/src/zwift-api/zwift_messages.pb.swift new file mode 100644 index 000000000..51e478cb3 --- /dev/null +++ b/src/zwift-api/zwift_messages.pb.swift @@ -0,0 +1,1693 @@ +// DO NOT EDIT. +// swift-format-ignore-file +// +// Generated by the Swift generator plugin for the protocol buffer compiler. +// Source: zwift_messages.proto +// +// For information on using the generated types, please see the documentation: +// https://github.com/apple/swift-protobuf/ + +import Foundation +import SwiftProtobuf + +// If the compiler emits an error on this type, it is because this file +// was generated by a version of the `protoc` Swift plug-in that is +// incompatible with the version of SwiftProtobuf to which you are linking. +// Please ensure that you are building against the same version of the API +// that was used to generate this file. +fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck { + struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {} + typealias Version = _2 +} + +struct PlayerState { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var id: Int32 { + get {return _storage._id} + set {_uniqueStorage()._id = newValue} + } + + var worldTime: Int64 { + get {return _storage._worldTime} + set {_uniqueStorage()._worldTime = newValue} + } + + var distance: Int32 { + get {return _storage._distance} + set {_uniqueStorage()._distance = newValue} + } + + var roadTime: Int32 { + get {return _storage._roadTime} + set {_uniqueStorage()._roadTime = newValue} + } + + var laps: Int32 { + get {return _storage._laps} + set {_uniqueStorage()._laps = newValue} + } + + var speed: Int32 { + get {return _storage._speed} + set {_uniqueStorage()._speed = newValue} + } + + var roadPosition: Int32 { + get {return _storage._roadPosition} + set {_uniqueStorage()._roadPosition = newValue} + } + + var cadenceUhz: Int32 { + get {return _storage._cadenceUhz} + set {_uniqueStorage()._cadenceUhz = newValue} + } + + var heartrate: Int32 { + get {return _storage._heartrate} + set {_uniqueStorage()._heartrate = newValue} + } + + var power: Int32 { + get {return _storage._power} + set {_uniqueStorage()._power = newValue} + } + + var heading: Int64 { + get {return _storage._heading} + set {_uniqueStorage()._heading = newValue} + } + + var lean: Int32 { + get {return _storage._lean} + set {_uniqueStorage()._lean = newValue} + } + + var climbing: Int32 { + get {return _storage._climbing} + set {_uniqueStorage()._climbing = newValue} + } + + var time: Int32 { + get {return _storage._time} + set {_uniqueStorage()._time = newValue} + } + + var f19: Int32 { + get {return _storage._f19} + set {_uniqueStorage()._f19 = newValue} + } + + var f20: Int32 { + get {return _storage._f20} + set {_uniqueStorage()._f20 = newValue} + } + + var progress: Int32 { + get {return _storage._progress} + set {_uniqueStorage()._progress = newValue} + } + + var customisationID: Int64 { + get {return _storage._customisationID} + set {_uniqueStorage()._customisationID = newValue} + } + + var justWatching: Int32 { + get {return _storage._justWatching} + set {_uniqueStorage()._justWatching = newValue} + } + + var calories: Int32 { + get {return _storage._calories} + set {_uniqueStorage()._calories = newValue} + } + + var x: Float { + get {return _storage._x} + set {_uniqueStorage()._x = newValue} + } + + var altitude: Float { + get {return _storage._altitude} + set {_uniqueStorage()._altitude = newValue} + } + + var y: Float { + get {return _storage._y} + set {_uniqueStorage()._y = newValue} + } + + var watchingRiderID: Int32 { + get {return _storage._watchingRiderID} + set {_uniqueStorage()._watchingRiderID = newValue} + } + + var groupID: Int32 { + get {return _storage._groupID} + set {_uniqueStorage()._groupID = newValue} + } + + var sport: Int64 { + get {return _storage._sport} + set {_uniqueStorage()._sport = newValue} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _storage = _StorageClass.defaultInstance +} + +struct ClientToServer { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var connected: Int32 = 0 + + var riderID: Int32 = 0 + + var worldTime: Int64 = 0 + + var state: PlayerState { + get {return _state ?? PlayerState()} + set {_state = newValue} + } + /// Returns true if `state` has been explicitly set. + var hasState: Bool {return self._state != nil} + /// Clears the value of `state`. Subsequent reads from it will return its default value. + mutating func clearState() {self._state = nil} + + var seqno: Int32 = 0 + + var tag8: Int64 = 0 + + var tag9: Int64 = 0 + + var lastUpdate: Int64 = 0 + + var tag11: Int64 = 0 + + var lastPlayerUpdate: Int64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _state: PlayerState? = nil +} + +struct SegmentResult { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var id: Int64 = 0 + + var riderID: Int64 = 0 + + var eventSubgroupID: Int64 = 0 + + var firstName: String = String() + + var lastName: String = String() + + var finishTimeStr: String = String() + + var elapsedMs: Int64 = 0 + + var powermeter: Int32 = 0 + + var weight: Int32 = 0 + + var power: Int32 = 0 + + var heartrate: Int32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct SegmentResults { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var worldID: Int64 = 0 + + var segmentID: Int64 = 0 + + var eventSubgroupID: Int64 = 0 + + var segmentResults: [SegmentResult] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// string firstName=7; +/// string lastName=8; +/// string timestamp=17; +struct UnknownMessage1 { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +/// int64 tag1=1; +/// UnknownMessage1 tag4=4; +struct UnknownMessage { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct ServerToClient { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var tag1: Int32 = 0 + + var riderID: Int32 = 0 + + var worldTime: Int64 = 0 + + var seqno: Int32 = 0 + + var playerStates: [PlayerState] = [] + + var playerUpdates: [UnknownMessage] = [] + + var tag11: Int64 = 0 + + var tag17: Int64 = 0 + + var numMsgs: Int32 = 0 + + var msgnum: Int32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct WorldAttributes { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var worldID: Int32 = 0 + + var name: String = String() + + var tag3: Int64 = 0 + + var tag5: Int64 = 0 + + var worldTime: Int64 = 0 + + var clockTime: Int64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct WorldAttribute { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var worldTime: Int64 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct EventSubgroupProtobuf { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var id: Int32 = 0 + + var name: String = String() + + var rules: Int32 = 0 + + var route: Int32 = 0 + + var laps: Int32 = 0 + + var startLocation: Int32 = 0 + + var label: Int32 = 0 + + var paceType: Int32 = 0 + + var jerseyHash: Int32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct RiderAttributes { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var f2: Int32 = 0 + + var f3: Int32 = 0 + + var attributeMessage: RiderAttributes.AttributeMessage { + get {return _attributeMessage ?? RiderAttributes.AttributeMessage()} + set {_attributeMessage = newValue} + } + /// Returns true if `attributeMessage` has been explicitly set. + var hasAttributeMessage: Bool {return self._attributeMessage != nil} + /// Clears the value of `attributeMessage`. Subsequent reads from it will return its default value. + mutating func clearAttributeMessage() {self._attributeMessage = nil} + + var theirID: Int32 = 0 + + var f13: Int32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + struct AttributeMessage { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var myID: Int32 = 0 + + var theirID: Int32 = 0 + + var firstName: String = String() + + var lastName: String = String() + + var countryCode: Int32 = 0 + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + } + + init() {} + + fileprivate var _attributeMessage: RiderAttributes.AttributeMessage? = nil +} + +struct Profiles { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var profiles: [Profile] = [] + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} +} + +struct Profile { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + var id: Int32 { + get {return _storage._id} + set {_uniqueStorage()._id = newValue} + } + + var firstName: String { + get {return _storage._firstName} + set {_uniqueStorage()._firstName = newValue} + } + + var lastName: String { + get {return _storage._lastName} + set {_uniqueStorage()._lastName = newValue} + } + + var male: Int32 { + get {return _storage._male} + set {_uniqueStorage()._male = newValue} + } + + var weight: Int32 { + get {return _storage._weight} + set {_uniqueStorage()._weight = newValue} + } + + var bodyType: Int32 { + get {return _storage._bodyType} + set {_uniqueStorage()._bodyType = newValue} + } + + var countryCode: Int32 { + get {return _storage._countryCode} + set {_uniqueStorage()._countryCode = newValue} + } + + var totalDistance: Int32 { + get {return _storage._totalDistance} + set {_uniqueStorage()._totalDistance = newValue} + } + + var totalDistanceClimbed: Int32 { + get {return _storage._totalDistanceClimbed} + set {_uniqueStorage()._totalDistanceClimbed = newValue} + } + + var totalTimeInMinutes: Int32 { + get {return _storage._totalTimeInMinutes} + set {_uniqueStorage()._totalTimeInMinutes = newValue} + } + + var totalWattHours: Int32 { + get {return _storage._totalWattHours} + set {_uniqueStorage()._totalWattHours = newValue} + } + + var height: Int32 { + get {return _storage._height} + set {_uniqueStorage()._height = newValue} + } + + var totalExperiencePoints: Int32 { + get {return _storage._totalExperiencePoints} + set {_uniqueStorage()._totalExperiencePoints = newValue} + } + + var achievementLevel: Int32 { + get {return _storage._achievementLevel} + set {_uniqueStorage()._achievementLevel = newValue} + } + + var powerSource: Int32 { + get {return _storage._powerSource} + set {_uniqueStorage()._powerSource = newValue} + } + + var age: Int32 { + get {return _storage._age} + set {_uniqueStorage()._age = newValue} + } + + var launchedGameClient: String { + get {return _storage._launchedGameClient} + set {_uniqueStorage()._launchedGameClient = newValue} + } + + var currentActivityID: Int32 { + get {return _storage._currentActivityID} + set {_uniqueStorage()._currentActivityID = newValue} + } + + var unknownFields = SwiftProtobuf.UnknownStorage() + + init() {} + + fileprivate var _storage = _StorageClass.defaultInstance +} + +#if swift(>=5.5) && canImport(_Concurrency) +extension PlayerState: @unchecked Sendable {} +extension ClientToServer: @unchecked Sendable {} +extension SegmentResult: @unchecked Sendable {} +extension SegmentResults: @unchecked Sendable {} +extension UnknownMessage1: @unchecked Sendable {} +extension UnknownMessage: @unchecked Sendable {} +extension ServerToClient: @unchecked Sendable {} +extension WorldAttributes: @unchecked Sendable {} +extension WorldAttribute: @unchecked Sendable {} +extension EventSubgroupProtobuf: @unchecked Sendable {} +extension RiderAttributes: @unchecked Sendable {} +extension RiderAttributes.AttributeMessage: @unchecked Sendable {} +extension Profiles: @unchecked Sendable {} +extension Profile: @unchecked Sendable {} +#endif // swift(>=5.5) && canImport(_Concurrency) + +// MARK: - Code below here is support for the SwiftProtobuf runtime. + +extension PlayerState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "PlayerState" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "id"), + 2: .same(proto: "worldTime"), + 3: .same(proto: "distance"), + 4: .same(proto: "roadTime"), + 5: .same(proto: "laps"), + 6: .same(proto: "speed"), + 8: .same(proto: "roadPosition"), + 9: .same(proto: "cadenceUHz"), + 11: .same(proto: "heartrate"), + 12: .same(proto: "power"), + 13: .same(proto: "heading"), + 14: .same(proto: "lean"), + 15: .same(proto: "climbing"), + 16: .same(proto: "time"), + 19: .same(proto: "f19"), + 20: .same(proto: "f20"), + 21: .same(proto: "progress"), + 22: .same(proto: "customisationId"), + 23: .same(proto: "justWatching"), + 24: .same(proto: "calories"), + 25: .same(proto: "x"), + 26: .same(proto: "altitude"), + 27: .same(proto: "y"), + 28: .same(proto: "watchingRiderId"), + 29: .same(proto: "groupId"), + 31: .same(proto: "sport"), + ] + + fileprivate class _StorageClass { + var _id: Int32 = 0 + var _worldTime: Int64 = 0 + var _distance: Int32 = 0 + var _roadTime: Int32 = 0 + var _laps: Int32 = 0 + var _speed: Int32 = 0 + var _roadPosition: Int32 = 0 + var _cadenceUhz: Int32 = 0 + var _heartrate: Int32 = 0 + var _power: Int32 = 0 + var _heading: Int64 = 0 + var _lean: Int32 = 0 + var _climbing: Int32 = 0 + var _time: Int32 = 0 + var _f19: Int32 = 0 + var _f20: Int32 = 0 + var _progress: Int32 = 0 + var _customisationID: Int64 = 0 + var _justWatching: Int32 = 0 + var _calories: Int32 = 0 + var _x: Float = 0 + var _altitude: Float = 0 + var _y: Float = 0 + var _watchingRiderID: Int32 = 0 + var _groupID: Int32 = 0 + var _sport: Int64 = 0 + + static let defaultInstance = _StorageClass() + + private init() {} + + init(copying source: _StorageClass) { + _id = source._id + _worldTime = source._worldTime + _distance = source._distance + _roadTime = source._roadTime + _laps = source._laps + _speed = source._speed + _roadPosition = source._roadPosition + _cadenceUhz = source._cadenceUhz + _heartrate = source._heartrate + _power = source._power + _heading = source._heading + _lean = source._lean + _climbing = source._climbing + _time = source._time + _f19 = source._f19 + _f20 = source._f20 + _progress = source._progress + _customisationID = source._customisationID + _justWatching = source._justWatching + _calories = source._calories + _x = source._x + _altitude = source._altitude + _y = source._y + _watchingRiderID = source._watchingRiderID + _groupID = source._groupID + _sport = source._sport + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + + mutating func decodeMessage(decoder: inout D) throws { + _ = _uniqueStorage() + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt32Field(value: &_storage._id) }() + case 2: try { try decoder.decodeSingularInt64Field(value: &_storage._worldTime) }() + case 3: try { try decoder.decodeSingularInt32Field(value: &_storage._distance) }() + case 4: try { try decoder.decodeSingularInt32Field(value: &_storage._roadTime) }() + case 5: try { try decoder.decodeSingularInt32Field(value: &_storage._laps) }() + case 6: try { try decoder.decodeSingularInt32Field(value: &_storage._speed) }() + case 8: try { try decoder.decodeSingularInt32Field(value: &_storage._roadPosition) }() + case 9: try { try decoder.decodeSingularInt32Field(value: &_storage._cadenceUhz) }() + case 11: try { try decoder.decodeSingularInt32Field(value: &_storage._heartrate) }() + case 12: try { try decoder.decodeSingularInt32Field(value: &_storage._power) }() + case 13: try { try decoder.decodeSingularInt64Field(value: &_storage._heading) }() + case 14: try { try decoder.decodeSingularInt32Field(value: &_storage._lean) }() + case 15: try { try decoder.decodeSingularInt32Field(value: &_storage._climbing) }() + case 16: try { try decoder.decodeSingularInt32Field(value: &_storage._time) }() + case 19: try { try decoder.decodeSingularInt32Field(value: &_storage._f19) }() + case 20: try { try decoder.decodeSingularInt32Field(value: &_storage._f20) }() + case 21: try { try decoder.decodeSingularInt32Field(value: &_storage._progress) }() + case 22: try { try decoder.decodeSingularInt64Field(value: &_storage._customisationID) }() + case 23: try { try decoder.decodeSingularInt32Field(value: &_storage._justWatching) }() + case 24: try { try decoder.decodeSingularInt32Field(value: &_storage._calories) }() + case 25: try { try decoder.decodeSingularFloatField(value: &_storage._x) }() + case 26: try { try decoder.decodeSingularFloatField(value: &_storage._altitude) }() + case 27: try { try decoder.decodeSingularFloatField(value: &_storage._y) }() + case 28: try { try decoder.decodeSingularInt32Field(value: &_storage._watchingRiderID) }() + case 29: try { try decoder.decodeSingularInt32Field(value: &_storage._groupID) }() + case 31: try { try decoder.decodeSingularInt64Field(value: &_storage._sport) }() + default: break + } + } + } + } + + func traverse(visitor: inout V) throws { + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + if _storage._id != 0 { + try visitor.visitSingularInt32Field(value: _storage._id, fieldNumber: 1) + } + if _storage._worldTime != 0 { + try visitor.visitSingularInt64Field(value: _storage._worldTime, fieldNumber: 2) + } + if _storage._distance != 0 { + try visitor.visitSingularInt32Field(value: _storage._distance, fieldNumber: 3) + } + if _storage._roadTime != 0 { + try visitor.visitSingularInt32Field(value: _storage._roadTime, fieldNumber: 4) + } + if _storage._laps != 0 { + try visitor.visitSingularInt32Field(value: _storage._laps, fieldNumber: 5) + } + if _storage._speed != 0 { + try visitor.visitSingularInt32Field(value: _storage._speed, fieldNumber: 6) + } + if _storage._roadPosition != 0 { + try visitor.visitSingularInt32Field(value: _storage._roadPosition, fieldNumber: 8) + } + if _storage._cadenceUhz != 0 { + try visitor.visitSingularInt32Field(value: _storage._cadenceUhz, fieldNumber: 9) + } + if _storage._heartrate != 0 { + try visitor.visitSingularInt32Field(value: _storage._heartrate, fieldNumber: 11) + } + if _storage._power != 0 { + try visitor.visitSingularInt32Field(value: _storage._power, fieldNumber: 12) + } + if _storage._heading != 0 { + try visitor.visitSingularInt64Field(value: _storage._heading, fieldNumber: 13) + } + if _storage._lean != 0 { + try visitor.visitSingularInt32Field(value: _storage._lean, fieldNumber: 14) + } + if _storage._climbing != 0 { + try visitor.visitSingularInt32Field(value: _storage._climbing, fieldNumber: 15) + } + if _storage._time != 0 { + try visitor.visitSingularInt32Field(value: _storage._time, fieldNumber: 16) + } + if _storage._f19 != 0 { + try visitor.visitSingularInt32Field(value: _storage._f19, fieldNumber: 19) + } + if _storage._f20 != 0 { + try visitor.visitSingularInt32Field(value: _storage._f20, fieldNumber: 20) + } + if _storage._progress != 0 { + try visitor.visitSingularInt32Field(value: _storage._progress, fieldNumber: 21) + } + if _storage._customisationID != 0 { + try visitor.visitSingularInt64Field(value: _storage._customisationID, fieldNumber: 22) + } + if _storage._justWatching != 0 { + try visitor.visitSingularInt32Field(value: _storage._justWatching, fieldNumber: 23) + } + if _storage._calories != 0 { + try visitor.visitSingularInt32Field(value: _storage._calories, fieldNumber: 24) + } + if _storage._x != 0 { + try visitor.visitSingularFloatField(value: _storage._x, fieldNumber: 25) + } + if _storage._altitude != 0 { + try visitor.visitSingularFloatField(value: _storage._altitude, fieldNumber: 26) + } + if _storage._y != 0 { + try visitor.visitSingularFloatField(value: _storage._y, fieldNumber: 27) + } + if _storage._watchingRiderID != 0 { + try visitor.visitSingularInt32Field(value: _storage._watchingRiderID, fieldNumber: 28) + } + if _storage._groupID != 0 { + try visitor.visitSingularInt32Field(value: _storage._groupID, fieldNumber: 29) + } + if _storage._sport != 0 { + try visitor.visitSingularInt64Field(value: _storage._sport, fieldNumber: 31) + } + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: PlayerState, rhs: PlayerState) -> Bool { + if lhs._storage !== rhs._storage { + let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in + let _storage = _args.0 + let rhs_storage = _args.1 + if _storage._id != rhs_storage._id {return false} + if _storage._worldTime != rhs_storage._worldTime {return false} + if _storage._distance != rhs_storage._distance {return false} + if _storage._roadTime != rhs_storage._roadTime {return false} + if _storage._laps != rhs_storage._laps {return false} + if _storage._speed != rhs_storage._speed {return false} + if _storage._roadPosition != rhs_storage._roadPosition {return false} + if _storage._cadenceUhz != rhs_storage._cadenceUhz {return false} + if _storage._heartrate != rhs_storage._heartrate {return false} + if _storage._power != rhs_storage._power {return false} + if _storage._heading != rhs_storage._heading {return false} + if _storage._lean != rhs_storage._lean {return false} + if _storage._climbing != rhs_storage._climbing {return false} + if _storage._time != rhs_storage._time {return false} + if _storage._f19 != rhs_storage._f19 {return false} + if _storage._f20 != rhs_storage._f20 {return false} + if _storage._progress != rhs_storage._progress {return false} + if _storage._customisationID != rhs_storage._customisationID {return false} + if _storage._justWatching != rhs_storage._justWatching {return false} + if _storage._calories != rhs_storage._calories {return false} + if _storage._x != rhs_storage._x {return false} + if _storage._altitude != rhs_storage._altitude {return false} + if _storage._y != rhs_storage._y {return false} + if _storage._watchingRiderID != rhs_storage._watchingRiderID {return false} + if _storage._groupID != rhs_storage._groupID {return false} + if _storage._sport != rhs_storage._sport {return false} + return true + } + if !storagesAreEqual {return false} + } + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ClientToServer: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "ClientToServer" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "connected"), + 2: .standard(proto: "rider_id"), + 3: .standard(proto: "world_time"), + 7: .same(proto: "state"), + 4: .same(proto: "seqno"), + 8: .same(proto: "tag8"), + 9: .same(proto: "tag9"), + 10: .standard(proto: "last_update"), + 11: .same(proto: "tag11"), + 12: .standard(proto: "last_player_update"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt32Field(value: &self.connected) }() + case 2: try { try decoder.decodeSingularInt32Field(value: &self.riderID) }() + case 3: try { try decoder.decodeSingularInt64Field(value: &self.worldTime) }() + case 4: try { try decoder.decodeSingularInt32Field(value: &self.seqno) }() + case 7: try { try decoder.decodeSingularMessageField(value: &self._state) }() + case 8: try { try decoder.decodeSingularInt64Field(value: &self.tag8) }() + case 9: try { try decoder.decodeSingularInt64Field(value: &self.tag9) }() + case 10: try { try decoder.decodeSingularInt64Field(value: &self.lastUpdate) }() + case 11: try { try decoder.decodeSingularInt64Field(value: &self.tag11) }() + case 12: try { try decoder.decodeSingularInt64Field(value: &self.lastPlayerUpdate) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if self.connected != 0 { + try visitor.visitSingularInt32Field(value: self.connected, fieldNumber: 1) + } + if self.riderID != 0 { + try visitor.visitSingularInt32Field(value: self.riderID, fieldNumber: 2) + } + if self.worldTime != 0 { + try visitor.visitSingularInt64Field(value: self.worldTime, fieldNumber: 3) + } + if self.seqno != 0 { + try visitor.visitSingularInt32Field(value: self.seqno, fieldNumber: 4) + } + try { if let v = self._state { + try visitor.visitSingularMessageField(value: v, fieldNumber: 7) + } }() + if self.tag8 != 0 { + try visitor.visitSingularInt64Field(value: self.tag8, fieldNumber: 8) + } + if self.tag9 != 0 { + try visitor.visitSingularInt64Field(value: self.tag9, fieldNumber: 9) + } + if self.lastUpdate != 0 { + try visitor.visitSingularInt64Field(value: self.lastUpdate, fieldNumber: 10) + } + if self.tag11 != 0 { + try visitor.visitSingularInt64Field(value: self.tag11, fieldNumber: 11) + } + if self.lastPlayerUpdate != 0 { + try visitor.visitSingularInt64Field(value: self.lastPlayerUpdate, fieldNumber: 12) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ClientToServer, rhs: ClientToServer) -> Bool { + if lhs.connected != rhs.connected {return false} + if lhs.riderID != rhs.riderID {return false} + if lhs.worldTime != rhs.worldTime {return false} + if lhs._state != rhs._state {return false} + if lhs.seqno != rhs.seqno {return false} + if lhs.tag8 != rhs.tag8 {return false} + if lhs.tag9 != rhs.tag9 {return false} + if lhs.lastUpdate != rhs.lastUpdate {return false} + if lhs.tag11 != rhs.tag11 {return false} + if lhs.lastPlayerUpdate != rhs.lastPlayerUpdate {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension SegmentResult: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "SegmentResult" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "id"), + 2: .standard(proto: "rider_id"), + 6: .standard(proto: "event_subgroup_id"), + 7: .standard(proto: "first_name"), + 8: .standard(proto: "last_name"), + 10: .standard(proto: "finish_time_str"), + 11: .standard(proto: "elapsed_ms"), + 12: .same(proto: "powermeter"), + 13: .same(proto: "weight"), + 15: .same(proto: "power"), + 19: .same(proto: "heartrate"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt64Field(value: &self.id) }() + case 2: try { try decoder.decodeSingularInt64Field(value: &self.riderID) }() + case 6: try { try decoder.decodeSingularInt64Field(value: &self.eventSubgroupID) }() + case 7: try { try decoder.decodeSingularStringField(value: &self.firstName) }() + case 8: try { try decoder.decodeSingularStringField(value: &self.lastName) }() + case 10: try { try decoder.decodeSingularStringField(value: &self.finishTimeStr) }() + case 11: try { try decoder.decodeSingularInt64Field(value: &self.elapsedMs) }() + case 12: try { try decoder.decodeSingularInt32Field(value: &self.powermeter) }() + case 13: try { try decoder.decodeSingularInt32Field(value: &self.weight) }() + case 15: try { try decoder.decodeSingularInt32Field(value: &self.power) }() + case 19: try { try decoder.decodeSingularInt32Field(value: &self.heartrate) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.id != 0 { + try visitor.visitSingularInt64Field(value: self.id, fieldNumber: 1) + } + if self.riderID != 0 { + try visitor.visitSingularInt64Field(value: self.riderID, fieldNumber: 2) + } + if self.eventSubgroupID != 0 { + try visitor.visitSingularInt64Field(value: self.eventSubgroupID, fieldNumber: 6) + } + if !self.firstName.isEmpty { + try visitor.visitSingularStringField(value: self.firstName, fieldNumber: 7) + } + if !self.lastName.isEmpty { + try visitor.visitSingularStringField(value: self.lastName, fieldNumber: 8) + } + if !self.finishTimeStr.isEmpty { + try visitor.visitSingularStringField(value: self.finishTimeStr, fieldNumber: 10) + } + if self.elapsedMs != 0 { + try visitor.visitSingularInt64Field(value: self.elapsedMs, fieldNumber: 11) + } + if self.powermeter != 0 { + try visitor.visitSingularInt32Field(value: self.powermeter, fieldNumber: 12) + } + if self.weight != 0 { + try visitor.visitSingularInt32Field(value: self.weight, fieldNumber: 13) + } + if self.power != 0 { + try visitor.visitSingularInt32Field(value: self.power, fieldNumber: 15) + } + if self.heartrate != 0 { + try visitor.visitSingularInt32Field(value: self.heartrate, fieldNumber: 19) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: SegmentResult, rhs: SegmentResult) -> Bool { + if lhs.id != rhs.id {return false} + if lhs.riderID != rhs.riderID {return false} + if lhs.eventSubgroupID != rhs.eventSubgroupID {return false} + if lhs.firstName != rhs.firstName {return false} + if lhs.lastName != rhs.lastName {return false} + if lhs.finishTimeStr != rhs.finishTimeStr {return false} + if lhs.elapsedMs != rhs.elapsedMs {return false} + if lhs.powermeter != rhs.powermeter {return false} + if lhs.weight != rhs.weight {return false} + if lhs.power != rhs.power {return false} + if lhs.heartrate != rhs.heartrate {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension SegmentResults: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "SegmentResults" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "world_id"), + 2: .standard(proto: "segment_id"), + 3: .standard(proto: "event_subgroup_id"), + 4: .standard(proto: "segment_results"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt64Field(value: &self.worldID) }() + case 2: try { try decoder.decodeSingularInt64Field(value: &self.segmentID) }() + case 3: try { try decoder.decodeSingularInt64Field(value: &self.eventSubgroupID) }() + case 4: try { try decoder.decodeRepeatedMessageField(value: &self.segmentResults) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.worldID != 0 { + try visitor.visitSingularInt64Field(value: self.worldID, fieldNumber: 1) + } + if self.segmentID != 0 { + try visitor.visitSingularInt64Field(value: self.segmentID, fieldNumber: 2) + } + if self.eventSubgroupID != 0 { + try visitor.visitSingularInt64Field(value: self.eventSubgroupID, fieldNumber: 3) + } + if !self.segmentResults.isEmpty { + try visitor.visitRepeatedMessageField(value: self.segmentResults, fieldNumber: 4) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: SegmentResults, rhs: SegmentResults) -> Bool { + if lhs.worldID != rhs.worldID {return false} + if lhs.segmentID != rhs.segmentID {return false} + if lhs.eventSubgroupID != rhs.eventSubgroupID {return false} + if lhs.segmentResults != rhs.segmentResults {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension UnknownMessage1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "UnknownMessage1" + static let _protobuf_nameMap = SwiftProtobuf._NameMap() + + mutating func decodeMessage(decoder: inout D) throws { + while let _ = try decoder.nextFieldNumber() { + } + } + + func traverse(visitor: inout V) throws { + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: UnknownMessage1, rhs: UnknownMessage1) -> Bool { + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension UnknownMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "UnknownMessage" + static let _protobuf_nameMap = SwiftProtobuf._NameMap() + + mutating func decodeMessage(decoder: inout D) throws { + while let _ = try decoder.nextFieldNumber() { + } + } + + func traverse(visitor: inout V) throws { + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: UnknownMessage, rhs: UnknownMessage) -> Bool { + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension ServerToClient: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "ServerToClient" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "tag1"), + 2: .standard(proto: "rider_id"), + 3: .standard(proto: "world_time"), + 4: .same(proto: "seqno"), + 8: .standard(proto: "player_states"), + 9: .standard(proto: "player_updates"), + 11: .same(proto: "tag11"), + 17: .same(proto: "tag17"), + 18: .standard(proto: "num_msgs"), + 19: .same(proto: "msgnum"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt32Field(value: &self.tag1) }() + case 2: try { try decoder.decodeSingularInt32Field(value: &self.riderID) }() + case 3: try { try decoder.decodeSingularInt64Field(value: &self.worldTime) }() + case 4: try { try decoder.decodeSingularInt32Field(value: &self.seqno) }() + case 8: try { try decoder.decodeRepeatedMessageField(value: &self.playerStates) }() + case 9: try { try decoder.decodeRepeatedMessageField(value: &self.playerUpdates) }() + case 11: try { try decoder.decodeSingularInt64Field(value: &self.tag11) }() + case 17: try { try decoder.decodeSingularInt64Field(value: &self.tag17) }() + case 18: try { try decoder.decodeSingularInt32Field(value: &self.numMsgs) }() + case 19: try { try decoder.decodeSingularInt32Field(value: &self.msgnum) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.tag1 != 0 { + try visitor.visitSingularInt32Field(value: self.tag1, fieldNumber: 1) + } + if self.riderID != 0 { + try visitor.visitSingularInt32Field(value: self.riderID, fieldNumber: 2) + } + if self.worldTime != 0 { + try visitor.visitSingularInt64Field(value: self.worldTime, fieldNumber: 3) + } + if self.seqno != 0 { + try visitor.visitSingularInt32Field(value: self.seqno, fieldNumber: 4) + } + if !self.playerStates.isEmpty { + try visitor.visitRepeatedMessageField(value: self.playerStates, fieldNumber: 8) + } + if !self.playerUpdates.isEmpty { + try visitor.visitRepeatedMessageField(value: self.playerUpdates, fieldNumber: 9) + } + if self.tag11 != 0 { + try visitor.visitSingularInt64Field(value: self.tag11, fieldNumber: 11) + } + if self.tag17 != 0 { + try visitor.visitSingularInt64Field(value: self.tag17, fieldNumber: 17) + } + if self.numMsgs != 0 { + try visitor.visitSingularInt32Field(value: self.numMsgs, fieldNumber: 18) + } + if self.msgnum != 0 { + try visitor.visitSingularInt32Field(value: self.msgnum, fieldNumber: 19) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: ServerToClient, rhs: ServerToClient) -> Bool { + if lhs.tag1 != rhs.tag1 {return false} + if lhs.riderID != rhs.riderID {return false} + if lhs.worldTime != rhs.worldTime {return false} + if lhs.seqno != rhs.seqno {return false} + if lhs.playerStates != rhs.playerStates {return false} + if lhs.playerUpdates != rhs.playerUpdates {return false} + if lhs.tag11 != rhs.tag11 {return false} + if lhs.tag17 != rhs.tag17 {return false} + if lhs.numMsgs != rhs.numMsgs {return false} + if lhs.msgnum != rhs.msgnum {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension WorldAttributes: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "WorldAttributes" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .standard(proto: "world_id"), + 2: .same(proto: "name"), + 3: .same(proto: "tag3"), + 4: .same(proto: "tag5"), + 6: .standard(proto: "world_time"), + 7: .standard(proto: "clock_time"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt32Field(value: &self.worldID) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.name) }() + case 3: try { try decoder.decodeSingularInt64Field(value: &self.tag3) }() + case 4: try { try decoder.decodeSingularInt64Field(value: &self.tag5) }() + case 6: try { try decoder.decodeSingularInt64Field(value: &self.worldTime) }() + case 7: try { try decoder.decodeSingularInt64Field(value: &self.clockTime) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.worldID != 0 { + try visitor.visitSingularInt32Field(value: self.worldID, fieldNumber: 1) + } + if !self.name.isEmpty { + try visitor.visitSingularStringField(value: self.name, fieldNumber: 2) + } + if self.tag3 != 0 { + try visitor.visitSingularInt64Field(value: self.tag3, fieldNumber: 3) + } + if self.tag5 != 0 { + try visitor.visitSingularInt64Field(value: self.tag5, fieldNumber: 4) + } + if self.worldTime != 0 { + try visitor.visitSingularInt64Field(value: self.worldTime, fieldNumber: 6) + } + if self.clockTime != 0 { + try visitor.visitSingularInt64Field(value: self.clockTime, fieldNumber: 7) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: WorldAttributes, rhs: WorldAttributes) -> Bool { + if lhs.worldID != rhs.worldID {return false} + if lhs.name != rhs.name {return false} + if lhs.tag3 != rhs.tag3 {return false} + if lhs.tag5 != rhs.tag5 {return false} + if lhs.worldTime != rhs.worldTime {return false} + if lhs.clockTime != rhs.clockTime {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension WorldAttribute: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "WorldAttribute" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 2: .standard(proto: "world_time"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 2: try { try decoder.decodeSingularInt64Field(value: &self.worldTime) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.worldTime != 0 { + try visitor.visitSingularInt64Field(value: self.worldTime, fieldNumber: 2) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: WorldAttribute, rhs: WorldAttribute) -> Bool { + if lhs.worldTime != rhs.worldTime {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension EventSubgroupProtobuf: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "EventSubgroupProtobuf" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "id"), + 2: .same(proto: "name"), + 8: .same(proto: "rules"), + 22: .same(proto: "route"), + 25: .same(proto: "laps"), + 29: .same(proto: "startLocation"), + 30: .same(proto: "label"), + 31: .same(proto: "paceType"), + 36: .same(proto: "jerseyHash"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt32Field(value: &self.id) }() + case 2: try { try decoder.decodeSingularStringField(value: &self.name) }() + case 8: try { try decoder.decodeSingularInt32Field(value: &self.rules) }() + case 22: try { try decoder.decodeSingularInt32Field(value: &self.route) }() + case 25: try { try decoder.decodeSingularInt32Field(value: &self.laps) }() + case 29: try { try decoder.decodeSingularInt32Field(value: &self.startLocation) }() + case 30: try { try decoder.decodeSingularInt32Field(value: &self.label) }() + case 31: try { try decoder.decodeSingularInt32Field(value: &self.paceType) }() + case 36: try { try decoder.decodeSingularInt32Field(value: &self.jerseyHash) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.id != 0 { + try visitor.visitSingularInt32Field(value: self.id, fieldNumber: 1) + } + if !self.name.isEmpty { + try visitor.visitSingularStringField(value: self.name, fieldNumber: 2) + } + if self.rules != 0 { + try visitor.visitSingularInt32Field(value: self.rules, fieldNumber: 8) + } + if self.route != 0 { + try visitor.visitSingularInt32Field(value: self.route, fieldNumber: 22) + } + if self.laps != 0 { + try visitor.visitSingularInt32Field(value: self.laps, fieldNumber: 25) + } + if self.startLocation != 0 { + try visitor.visitSingularInt32Field(value: self.startLocation, fieldNumber: 29) + } + if self.label != 0 { + try visitor.visitSingularInt32Field(value: self.label, fieldNumber: 30) + } + if self.paceType != 0 { + try visitor.visitSingularInt32Field(value: self.paceType, fieldNumber: 31) + } + if self.jerseyHash != 0 { + try visitor.visitSingularInt32Field(value: self.jerseyHash, fieldNumber: 36) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: EventSubgroupProtobuf, rhs: EventSubgroupProtobuf) -> Bool { + if lhs.id != rhs.id {return false} + if lhs.name != rhs.name {return false} + if lhs.rules != rhs.rules {return false} + if lhs.route != rhs.route {return false} + if lhs.laps != rhs.laps {return false} + if lhs.startLocation != rhs.startLocation {return false} + if lhs.label != rhs.label {return false} + if lhs.paceType != rhs.paceType {return false} + if lhs.jerseyHash != rhs.jerseyHash {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension RiderAttributes: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "RiderAttributes" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 2: .same(proto: "f2"), + 3: .same(proto: "f3"), + 4: .same(proto: "attributeMessage"), + 10: .same(proto: "theirId"), + 13: .same(proto: "f13"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 2: try { try decoder.decodeSingularInt32Field(value: &self.f2) }() + case 3: try { try decoder.decodeSingularInt32Field(value: &self.f3) }() + case 4: try { try decoder.decodeSingularMessageField(value: &self._attributeMessage) }() + case 10: try { try decoder.decodeSingularInt32Field(value: &self.theirID) }() + case 13: try { try decoder.decodeSingularInt32Field(value: &self.f13) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every if/case branch local when no optimizations + // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and + // https://github.com/apple/swift-protobuf/issues/1182 + if self.f2 != 0 { + try visitor.visitSingularInt32Field(value: self.f2, fieldNumber: 2) + } + if self.f3 != 0 { + try visitor.visitSingularInt32Field(value: self.f3, fieldNumber: 3) + } + try { if let v = self._attributeMessage { + try visitor.visitSingularMessageField(value: v, fieldNumber: 4) + } }() + if self.theirID != 0 { + try visitor.visitSingularInt32Field(value: self.theirID, fieldNumber: 10) + } + if self.f13 != 0 { + try visitor.visitSingularInt32Field(value: self.f13, fieldNumber: 13) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: RiderAttributes, rhs: RiderAttributes) -> Bool { + if lhs.f2 != rhs.f2 {return false} + if lhs.f3 != rhs.f3 {return false} + if lhs._attributeMessage != rhs._attributeMessage {return false} + if lhs.theirID != rhs.theirID {return false} + if lhs.f13 != rhs.f13 {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension RiderAttributes.AttributeMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = RiderAttributes.protoMessageName + ".AttributeMessage" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "myId"), + 2: .same(proto: "theirId"), + 3: .same(proto: "firstName"), + 4: .same(proto: "lastName"), + 5: .same(proto: "countryCode"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt32Field(value: &self.myID) }() + case 2: try { try decoder.decodeSingularInt32Field(value: &self.theirID) }() + case 3: try { try decoder.decodeSingularStringField(value: &self.firstName) }() + case 4: try { try decoder.decodeSingularStringField(value: &self.lastName) }() + case 5: try { try decoder.decodeSingularInt32Field(value: &self.countryCode) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if self.myID != 0 { + try visitor.visitSingularInt32Field(value: self.myID, fieldNumber: 1) + } + if self.theirID != 0 { + try visitor.visitSingularInt32Field(value: self.theirID, fieldNumber: 2) + } + if !self.firstName.isEmpty { + try visitor.visitSingularStringField(value: self.firstName, fieldNumber: 3) + } + if !self.lastName.isEmpty { + try visitor.visitSingularStringField(value: self.lastName, fieldNumber: 4) + } + if self.countryCode != 0 { + try visitor.visitSingularInt32Field(value: self.countryCode, fieldNumber: 5) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: RiderAttributes.AttributeMessage, rhs: RiderAttributes.AttributeMessage) -> Bool { + if lhs.myID != rhs.myID {return false} + if lhs.theirID != rhs.theirID {return false} + if lhs.firstName != rhs.firstName {return false} + if lhs.lastName != rhs.lastName {return false} + if lhs.countryCode != rhs.countryCode {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Profiles: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "Profiles" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "profiles"), + ] + + mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeRepeatedMessageField(value: &self.profiles) }() + default: break + } + } + } + + func traverse(visitor: inout V) throws { + if !self.profiles.isEmpty { + try visitor.visitRepeatedMessageField(value: self.profiles, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Profiles, rhs: Profiles) -> Bool { + if lhs.profiles != rhs.profiles {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} + +extension Profile: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + static let protoMessageName: String = "Profile" + static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "id"), + 4: .same(proto: "firstName"), + 5: .same(proto: "lastName"), + 6: .same(proto: "male"), + 9: .same(proto: "weight"), + 12: .same(proto: "bodyType"), + 34: .same(proto: "countryCode"), + 35: .same(proto: "totalDistance"), + 36: .same(proto: "totalDistanceClimbed"), + 37: .same(proto: "totalTimeInMinutes"), + 41: .same(proto: "totalWattHours"), + 42: .same(proto: "height"), + 46: .same(proto: "totalExperiencePoints"), + 49: .same(proto: "achievementLevel"), + 52: .same(proto: "powerSource"), + 55: .same(proto: "age"), + 108: .same(proto: "launchedGameClient"), + 109: .same(proto: "currentActivityId"), + ] + + fileprivate class _StorageClass { + var _id: Int32 = 0 + var _firstName: String = String() + var _lastName: String = String() + var _male: Int32 = 0 + var _weight: Int32 = 0 + var _bodyType: Int32 = 0 + var _countryCode: Int32 = 0 + var _totalDistance: Int32 = 0 + var _totalDistanceClimbed: Int32 = 0 + var _totalTimeInMinutes: Int32 = 0 + var _totalWattHours: Int32 = 0 + var _height: Int32 = 0 + var _totalExperiencePoints: Int32 = 0 + var _achievementLevel: Int32 = 0 + var _powerSource: Int32 = 0 + var _age: Int32 = 0 + var _launchedGameClient: String = String() + var _currentActivityID: Int32 = 0 + + static let defaultInstance = _StorageClass() + + private init() {} + + init(copying source: _StorageClass) { + _id = source._id + _firstName = source._firstName + _lastName = source._lastName + _male = source._male + _weight = source._weight + _bodyType = source._bodyType + _countryCode = source._countryCode + _totalDistance = source._totalDistance + _totalDistanceClimbed = source._totalDistanceClimbed + _totalTimeInMinutes = source._totalTimeInMinutes + _totalWattHours = source._totalWattHours + _height = source._height + _totalExperiencePoints = source._totalExperiencePoints + _achievementLevel = source._achievementLevel + _powerSource = source._powerSource + _age = source._age + _launchedGameClient = source._launchedGameClient + _currentActivityID = source._currentActivityID + } + } + + fileprivate mutating func _uniqueStorage() -> _StorageClass { + if !isKnownUniquelyReferenced(&_storage) { + _storage = _StorageClass(copying: _storage) + } + return _storage + } + + mutating func decodeMessage(decoder: inout D) throws { + _ = _uniqueStorage() + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + while let fieldNumber = try decoder.nextFieldNumber() { + // The use of inline closures is to circumvent an issue where the compiler + // allocates stack space for every case branch when no optimizations are + // enabled. https://github.com/apple/swift-protobuf/issues/1034 + switch fieldNumber { + case 1: try { try decoder.decodeSingularInt32Field(value: &_storage._id) }() + case 4: try { try decoder.decodeSingularStringField(value: &_storage._firstName) }() + case 5: try { try decoder.decodeSingularStringField(value: &_storage._lastName) }() + case 6: try { try decoder.decodeSingularInt32Field(value: &_storage._male) }() + case 9: try { try decoder.decodeSingularInt32Field(value: &_storage._weight) }() + case 12: try { try decoder.decodeSingularInt32Field(value: &_storage._bodyType) }() + case 34: try { try decoder.decodeSingularInt32Field(value: &_storage._countryCode) }() + case 35: try { try decoder.decodeSingularInt32Field(value: &_storage._totalDistance) }() + case 36: try { try decoder.decodeSingularInt32Field(value: &_storage._totalDistanceClimbed) }() + case 37: try { try decoder.decodeSingularInt32Field(value: &_storage._totalTimeInMinutes) }() + case 41: try { try decoder.decodeSingularInt32Field(value: &_storage._totalWattHours) }() + case 42: try { try decoder.decodeSingularInt32Field(value: &_storage._height) }() + case 46: try { try decoder.decodeSingularInt32Field(value: &_storage._totalExperiencePoints) }() + case 49: try { try decoder.decodeSingularInt32Field(value: &_storage._achievementLevel) }() + case 52: try { try decoder.decodeSingularInt32Field(value: &_storage._powerSource) }() + case 55: try { try decoder.decodeSingularInt32Field(value: &_storage._age) }() + case 108: try { try decoder.decodeSingularStringField(value: &_storage._launchedGameClient) }() + case 109: try { try decoder.decodeSingularInt32Field(value: &_storage._currentActivityID) }() + default: break + } + } + } + } + + func traverse(visitor: inout V) throws { + try withExtendedLifetime(_storage) { (_storage: _StorageClass) in + if _storage._id != 0 { + try visitor.visitSingularInt32Field(value: _storage._id, fieldNumber: 1) + } + if !_storage._firstName.isEmpty { + try visitor.visitSingularStringField(value: _storage._firstName, fieldNumber: 4) + } + if !_storage._lastName.isEmpty { + try visitor.visitSingularStringField(value: _storage._lastName, fieldNumber: 5) + } + if _storage._male != 0 { + try visitor.visitSingularInt32Field(value: _storage._male, fieldNumber: 6) + } + if _storage._weight != 0 { + try visitor.visitSingularInt32Field(value: _storage._weight, fieldNumber: 9) + } + if _storage._bodyType != 0 { + try visitor.visitSingularInt32Field(value: _storage._bodyType, fieldNumber: 12) + } + if _storage._countryCode != 0 { + try visitor.visitSingularInt32Field(value: _storage._countryCode, fieldNumber: 34) + } + if _storage._totalDistance != 0 { + try visitor.visitSingularInt32Field(value: _storage._totalDistance, fieldNumber: 35) + } + if _storage._totalDistanceClimbed != 0 { + try visitor.visitSingularInt32Field(value: _storage._totalDistanceClimbed, fieldNumber: 36) + } + if _storage._totalTimeInMinutes != 0 { + try visitor.visitSingularInt32Field(value: _storage._totalTimeInMinutes, fieldNumber: 37) + } + if _storage._totalWattHours != 0 { + try visitor.visitSingularInt32Field(value: _storage._totalWattHours, fieldNumber: 41) + } + if _storage._height != 0 { + try visitor.visitSingularInt32Field(value: _storage._height, fieldNumber: 42) + } + if _storage._totalExperiencePoints != 0 { + try visitor.visitSingularInt32Field(value: _storage._totalExperiencePoints, fieldNumber: 46) + } + if _storage._achievementLevel != 0 { + try visitor.visitSingularInt32Field(value: _storage._achievementLevel, fieldNumber: 49) + } + if _storage._powerSource != 0 { + try visitor.visitSingularInt32Field(value: _storage._powerSource, fieldNumber: 52) + } + if _storage._age != 0 { + try visitor.visitSingularInt32Field(value: _storage._age, fieldNumber: 55) + } + if !_storage._launchedGameClient.isEmpty { + try visitor.visitSingularStringField(value: _storage._launchedGameClient, fieldNumber: 108) + } + if _storage._currentActivityID != 0 { + try visitor.visitSingularInt32Field(value: _storage._currentActivityID, fieldNumber: 109) + } + } + try unknownFields.traverse(visitor: &visitor) + } + + static func ==(lhs: Profile, rhs: Profile) -> Bool { + if lhs._storage !== rhs._storage { + let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in + let _storage = _args.0 + let rhs_storage = _args.1 + if _storage._id != rhs_storage._id {return false} + if _storage._firstName != rhs_storage._firstName {return false} + if _storage._lastName != rhs_storage._lastName {return false} + if _storage._male != rhs_storage._male {return false} + if _storage._weight != rhs_storage._weight {return false} + if _storage._bodyType != rhs_storage._bodyType {return false} + if _storage._countryCode != rhs_storage._countryCode {return false} + if _storage._totalDistance != rhs_storage._totalDistance {return false} + if _storage._totalDistanceClimbed != rhs_storage._totalDistanceClimbed {return false} + if _storage._totalTimeInMinutes != rhs_storage._totalTimeInMinutes {return false} + if _storage._totalWattHours != rhs_storage._totalWattHours {return false} + if _storage._height != rhs_storage._height {return false} + if _storage._totalExperiencePoints != rhs_storage._totalExperiencePoints {return false} + if _storage._achievementLevel != rhs_storage._achievementLevel {return false} + if _storage._powerSource != rhs_storage._powerSource {return false} + if _storage._age != rhs_storage._age {return false} + if _storage._launchedGameClient != rhs_storage._launchedGameClient {return false} + if _storage._currentActivityID != rhs_storage._currentActivityID {return false} + return true + } + if !storagesAreEqual {return false} + } + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/src/zwift-api/zwift_messages.proto b/src/zwift-api/zwift_messages.proto new file mode 100644 index 000000000..883f70822 --- /dev/null +++ b/src/zwift-api/zwift_messages.proto @@ -0,0 +1,153 @@ +syntax="proto3"; + +message PlayerState { + int32 id = 1; + int64 worldTime = 2; + int32 distance = 3; + int32 roadTime = 4; + int32 laps = 5; + int32 speed = 6; + int32 roadPosition = 8; + int32 cadenceUHz = 9; + int32 heartrate = 11; + int32 power = 12; + int64 heading = 13; + int32 lean = 14; + int32 climbing = 15; + int32 time = 16; + int32 f19 = 19; + int32 f20 = 20; + int32 progress = 21; + int64 customisationId = 22; + int32 justWatching = 23; + int32 calories = 24; + float x = 25; + float altitude = 26; + float y = 27; + int32 watchingRiderId = 28; + int32 groupId = 29; + int64 sport = 31; +} + +message ClientToServer { + int32 connected = 1; + int32 rider_id = 2; + int64 world_time = 3; + PlayerState state = 7; + int32 seqno = 4; + int64 tag8 = 8; + int64 tag9 = 9; + int64 last_update = 10; + int64 tag11 = 11; + int64 last_player_update = 12; +} + +message SegmentResult { + int64 id = 1; + int64 rider_id = 2; + int64 event_subgroup_id = 6; + string first_name = 7; + string last_name = 8; + string finish_time_str = 10; + int64 elapsed_ms = 11; + int32 powermeter = 12; + int32 weight = 13; + int32 power = 15; + int32 heartrate = 19; +} + +message SegmentResults { + int64 world_id = 1; + int64 segment_id = 2; + int64 event_subgroup_id = 3; + repeated SegmentResult segment_results = 4; +} + +message UnknownMessage1 { + // string firstName=7; + // string lastName=8; + // string timestamp=17; +} + +message UnknownMessage { + // int64 tag1=1; + // UnknownMessage1 tag4=4; +} + +message ServerToClient { + int32 tag1 = 1; + int32 rider_id = 2; + int64 world_time = 3; + int32 seqno = 4; + repeated PlayerState player_states = 8; + repeated UnknownMessage player_updates = 9; + int64 tag11 = 11; + int64 tag17 = 17; + int32 num_msgs = 18; + int32 msgnum = 19; +} + +message WorldAttributes { + int32 world_id = 1; + string name = 2; + int64 tag3 = 3; + int64 tag5 = 4; + int64 world_time = 6; + int64 clock_time = 7; +} + +message WorldAttribute { + int64 world_time = 2; +} + +message EventSubgroupProtobuf { + int32 id = 1; + string name = 2; + int32 rules = 8; + int32 route = 22; + int32 laps = 25; + int32 startLocation = 29; + int32 label = 30; + int32 paceType = 31; + int32 jerseyHash = 36; +} + +message RiderAttributes { + int32 f2 = 2; + int32 f3 = 3; + message AttributeMessage { + int32 myId = 1; + int32 theirId = 2; + string firstName = 3; + string lastName = 4; + int32 countryCode = 5; + } + AttributeMessage attributeMessage = 4; + int32 theirId = 10; + int32 f13 = 13; +} + +message Profiles { + repeated Profile profiles = 1; +} + +message Profile { + int32 id = 1; + string firstName = 4; + string lastName = 5; + int32 male = 6; + int32 weight = 9; + int32 bodyType = 12; + int32 countryCode = 34; + int32 totalDistance = 35; + int32 totalDistanceClimbed = 36; + int32 totalTimeInMinutes = 37; + int32 totalWattHours = 41; + int32 height = 42; + int32 totalExperiencePoints = 46; + int32 achievementLevel = 49; + int32 powerSource = 52; + int32 age = 55; + string launchedGameClient = 108; + int32 currentActivityId = 109; +} diff --git a/src/zwift-api/zwift_protobuf_layer.swift b/src/zwift-api/zwift_protobuf_layer.swift new file mode 100644 index 000000000..bb8a2b72c --- /dev/null +++ b/src/zwift-api/zwift_protobuf_layer.swift @@ -0,0 +1,47 @@ +// +// zwift_protobuf_layer.swift +// qdomyoszwift +// +// Created by Roberto Viola on 30/12/23. +// + +import Foundation +import SwiftProtobuf + +@objc public class zwift_protobuf_layer : NSObject { + var player: PlayerState! + let SwiftDebug = swiftDebug() + + @objc public func getPlayerState(value: Data) { + do { + //let hexString = value.map { String(format: "%02x", $0) }.joined() + //SwiftDebug.qtDebug("HEX \(hexString)") + let decodedInfo = try PlayerState(serializedData: value) + player = decodedInfo + } catch { + SwiftDebug.qtDebug("An error occurred: \(error)") + } + } + + @objc public func getAltitude() -> Float { + return player.altitude + } + + @objc public func getDistance() -> Int32 { + return player.distance + } + + @objc public func getLatitude() -> Float { + return player.x + } + + @objc public func getLongitude() -> Float { + return player.y + } + + /* + @objc public init() { + super.init() + }*/ + +} diff --git a/tst/Devices/KingsmithR2Treadmill/kingsmithr2treadmilltestdata.h b/tst/Devices/KingsmithR2Treadmill/kingsmithr2treadmilltestdata.h index f65e41aed..fc32df239 100644 --- a/tst/Devices/KingsmithR2Treadmill/kingsmithr2treadmilltestdata.h +++ b/tst/Devices/KingsmithR2Treadmill/kingsmithr2treadmilltestdata.h @@ -21,6 +21,9 @@ class KingsmithR2TreadmillTestData : public BluetoothDeviceTestData { this->addDeviceName("KS-NGCH-X21C", comparison::StartsWithIgnoreCase); this->addDeviceName("KS-NACH-X21C", comparison::StartsWithIgnoreCase); + // KingSmith Walking Pad G1 + this->addDeviceName("KS-NGCH-G1C", comparison::StartsWithIgnoreCase); + } diff --git a/tst/Devices/bluetoothdevicetestsuite.cpp b/tst/Devices/bluetoothdevicetestsuite.cpp index 43b9c8e27..615ff3592 100644 --- a/tst/Devices/bluetoothdevicetestsuite.cpp +++ b/tst/Devices/bluetoothdevicetestsuite.cpp @@ -12,6 +12,7 @@ void BluetoothDeviceTestSuite::tryDetectDevice(bluetooth &bt, try { // It is possible to use an EXPECT_NO_THROW here, but this // way is easier to place a breakpoint on the call to bt.deviceDiscovered. + bt.homeformLoaded = true; bt.deviceDiscovered(deviceInfo); } catch (...) { FAIL() << "Failed to perform device detection.";