Compare commits

..

41 Commits

Author SHA1 Message Date
Roberto Viola
a57408229b fixing linker error 2023-08-18 12:06:32 +02:00
Roberto Viola
82578e4923 Update build.gradle 2023-08-16 11:27:23 +02:00
Roberto Viola
4682c2b172 fixing path 2023-08-06 10:58:46 +02:00
Roberto Viola
64eace5ab9 keys added 2023-08-03 12:13:46 +02:00
Roberto Viola
b39b98b0d8 Update bluetooth.cpp 2023-08-03 10:23:33 +02:00
Roberto Viola
86e02be26e simplify the debug 2023-08-03 10:19:22 +02:00
Roberto Viola
b00e77a4ea Update qdomyos-zwift.pri 2023-08-03 09:28:17 +02:00
Roberto Viola
f80a8f4051 fixing models (en) 2023-08-03 08:47:46 +02:00
Roberto Viola
f45d3b9914 trying to fix models 2023-08-02 16:59:29 +02:00
Roberto Viola
bcb102e0dc not working yet 2023-07-28 22:25:56 +02:00
Roberto Viola
acee1b1301 adding assets to qt 2023-07-20 23:14:45 +02:00
Roberto Viola
0f9e7c0829 Revert "Revert "Revert "adding kotlin"""
This reverts commit 944d6d5ef2.
2023-07-20 17:53:01 +02:00
Roberto Viola
efd22aaee2 Update build.gradle 2023-07-20 17:52:56 +02:00
Roberto Viola
944d6d5ef2 Revert "Revert "adding kotlin""
This reverts commit 01e94e752c.
2023-07-20 15:54:59 +02:00
Roberto Viola
14fb0a5cde fixing build 2023-07-20 14:55:29 +02:00
Roberto Viola
da6faf18b5 Update ScreenCaptureService.java 2023-07-20 14:08:56 +02:00
Roberto Viola
6c662b20de Update ScreenCaptureService.java 2023-07-20 13:33:22 +02:00
Roberto Viola
75030bd25a Update ScreenCaptureService.java 2023-07-20 12:24:44 +02:00
Roberto Viola
a8b36057ce Update ScreenCaptureService.java 2023-07-20 11:56:22 +02:00
Roberto Viola
01e94e752c Revert "adding kotlin"
This reverts commit d83bcf984d.
2023-07-20 11:52:47 +02:00
Roberto Viola
d83bcf984d adding kotlin 2023-07-20 11:08:13 +02:00
Roberto Viola
ca93611acc Update build.gradle 2023-07-20 10:36:28 +02:00
Roberto Viola
9868a80be6 Update build.gradle 2023-07-20 09:23:21 +02:00
Roberto Viola
0d0db9fe3d added paddleocr4android 2023-07-20 08:20:36 +02:00
Roberto Viola
09affb4dd1 works but we need paddleocr too 2023-07-19 21:36:05 +02:00
Roberto Viola
ba1afdfa5a opencv works with zwift! 2023-07-19 21:25:26 +02:00
Roberto Viola
8ce3ae8ebd Update qdomyos-zwift.pri 2023-07-19 17:48:17 +02:00
Roberto Viola
6778364353 Update qdomyos-zwift.pri 2023-07-19 17:10:24 +02:00
Roberto Viola
1d4fa21899 Update qdomyos-zwift.pri 2023-07-19 16:40:11 +02:00
Roberto Viola
fa94706754 Update qdomyos-zwift.pri 2023-07-19 15:57:34 +02:00
Roberto Viola
3c5dc35675 updatung libopencv 2023-07-19 15:22:36 +02:00
Roberto Viola
bc5a1161df Update qdomyos-zwift.pri 2023-07-19 14:34:08 +02:00
Roberto Viola
7e5ff25d39 updating android_stl 2023-07-19 14:15:52 +02:00
Roberto Viola
0e46b52c64 updating opencv built against android-21 2023-07-19 13:14:06 +02:00
Roberto Viola
377381bb64 Revert "Update build.gradle"
This reverts commit 85558eda35.
2023-07-19 12:30:47 +02:00
Roberto Viola
85558eda35 Update build.gradle 2023-07-19 12:03:01 +02:00
Roberto Viola
8132e56483 Update qdomyos-zwift.pri 2023-07-19 11:29:19 +02:00
Roberto Viola
ab86534f31 linking libraries 2023-07-19 11:03:16 +02:00
Roberto Viola
ab92d03891 Update bluetooth.cpp 2023-07-19 10:23:07 +02:00
Roberto Viola
cb2980741e Update bluetooth.cpp 2023-07-18 16:57:13 +02:00
Roberto Viola
8304f43bc5 let's see if it builds 2023-07-18 10:08:40 +02:00
404 changed files with 100344 additions and 14473 deletions

View File

@@ -14,8 +14,8 @@ on:
branches: [ master, github-workflow-playground ]
pull_request:
branches: [ master ]
schedule:
- cron: "0 0 * * *"
# schedule:
# - cron: "0 */12 * * *"
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
@@ -70,20 +70,15 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version: 3.7
python-version: 3.10.11
- 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
@@ -122,20 +117,15 @@ 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
cd ..
make -j8
cd src/debug
mkdir output
@@ -143,17 +133,15 @@ jobs:
cp qdomyos-zwift.exe output/
cd output
windeployqt --qmldir ../../ qdomyos-zwift.exe
cp "C:/mingw64/bin/libwinpthread-1.dll" .
cp "C:/mingw64/bin/libgcc_s_seh-1.dll" .
cp "C:/mingw64/bin/libstdc++-6.dll" .
cp "C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/libwinpthread-1.dll" .
cp "C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/libgcc_s_seh-1.dll" .
cp "C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/libstdc++-6.dll" .
cp ../../../icons/iOS/iTunesArtwork@2x.png .
cp ../../AppxManifest.xml .
cp ../../windows/*.py .
cp ../../windows/*.bat .
cp ../../../windows_openssl/*.* .
mkdir adb
mkdir python
Copy-Item -Path C:\hostedtoolcache\windows\Python\3.7.9\x64 -Destination python -Recurse
Copy-Item -Path C:\hostedtoolcache\windows\Python\3.10.11\x64 -Destination python -Recurse
cp ../../adb/* adb/
cd ..
cd appx
@@ -163,6 +151,12 @@ 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
cd ..
make -j8
cd src/debug
mkdir output
@@ -170,12 +164,11 @@ jobs:
cp qdomyos-zwift.exe output/
cd output
windeployqt --qmldir ../../ qdomyos-zwift.exe
cp "C:/mingw64/bin/libwinpthread-1.dll" .
cp "C:/mingw64/bin/libgcc_s_seh-1.dll" .
cp "C:/mingw64/bin/libstdc++-6.dll" .
cp "C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/libwinpthread-1.dll" .
cp "C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/libgcc_s_seh-1.dll" .
cp "C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/libstdc++-6.dll" .
cp ../../../icons/iOS/iTunesArtwork@2x.png .
cp ../../AppxManifest.xml .
cp ../../../windows_openssl/*.* .
mkdir adb
cp ../../adb/* adb/
cd ..
@@ -183,79 +176,23 @@ jobs:
#../../MSIX-Toolkit/WindowsSDK/10/10.0.20348.0/x64/makeappx.exe pack /d ../output/ /p qz
if: matrix.config.python == false
- name: patching qt for bluetooth
run: cp qt-patches/windows/5.15.2/binary/mingw64/*.* ${{ github.workspace }}/src/debug/output/
- name: Zip artifact for deployment
run: Compress-Archive src/debug/output windows-binary.zip
if: matrix.config.python
- name: Zip artifact for deployment
run: Compress-Archive src/debug/output windows-binary-no-python.zip
if: ${{ ! matrix.config.python }}
run: Compress-Archive src/debug/output release.zip
- name: Archive windows binary
uses: actions/upload-artifact@v2
with:
name: windows-binary
path: windows-binary.zip
path: release.zip
if: matrix.config.python
- name: Archive windows binary
uses: actions/upload-artifact@v2
with:
name: windows-binary-no-python
path: windows-binary-no-python.zip
path: release.zip
if: ${{ ! matrix.config.python }}
# - name: Exit if not on master branch
# if: github.ref == 'refs/heads/main'
# run: exit 1
# - uses: actions/checkout@v3
# with:
# fetch-depth: 0 # Required due to the way Git works, without it this action won't be able to find any or the correct tags
# - name: Get previous tag
# id: previoustag
# uses: 'WyriHaximus/github-action-get-previous-tag@v1'
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# - name: Create Release
# if: ${{ ! matrix.config.python }}
# id: create_release
# uses: actions/create-release@v1
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# tag_name: ${{ steps.previoustag.outputs.tag }}
# release_name: Release ${{ steps.previoustag.outputs.tag }}
# draft: false
# prerelease: false
# - name: upload windows artifact
# uses: actions/upload-release-asset@v1
# if: ${{ ! matrix.config.python }}
# env:
# GITHUB_TOKEN: ${{ github.token }}
# with:
# upload_url: ${{ steps.create_release.outputs.upload_url }}
# asset_path: release.zip
# asset_name: windows-binary-no-python.zip
# asset_content_type: application/zip
# - name: upload windows artifact
# uses: actions/upload-release-asset@v1
# if: ${{ matrix.config.python }}
# env:
# GITHUB_TOKEN: ${{ github.token }}
# with:
# upload_url: ${{ steps.create_release.outputs.upload_url }}
# asset_path: release.zip
# asset_name: windows-binary.zip
# asset_content_type: application/zip
# window-steam-build:
# runs-on: windows-latest
#
@@ -306,7 +243,6 @@ jobs:
# 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
# echo "#define STEAM_STORE" >> secret.h
# cd ..
# make -j8
@@ -341,19 +277,6 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: release
uses: actions/create-release@v1
if: startsWith(github.ref, 'refs/tags/')
id: create_release
with:
draft: false
prerelease: false
release_name: ${{ steps.version.outputs.version }}
tag_name: ${{ github.ref }}
body_path: CHANGELOG.md
env:
GITHUB_TOKEN: ${{ github.token }}
# - name: Cache Qt Linux Desktop
# id: cache-qt-linux-desktop
# uses: actions/cache@v1
@@ -530,12 +453,30 @@ jobs:
sudo apt-get install -y xvfb
Xvfb -ac ${{ env.DISPLAY }} -screen 0 1280x780x24 &
- name: Checkout repository
# 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:
# 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
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"
- 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
@@ -572,7 +513,7 @@ jobs:
- name: Install Qt Android
uses: jurplel/install-qt-action@v3
with:
version: '5.15.0'
version: '5.15.2'
host: 'linux'
target: 'android'
arch: 'android'
@@ -586,20 +527,6 @@ jobs:
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '11'
- name: patching qt for bluetooth
run: cp qt-patches/android/5.15.0/jar/*.* ${{ github.workspace }}/output/android/Qt/5.15.0/android/jar/
- name: 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
make -j8
make install
cd ../..
- name: Set Android NDK 21 && build
run: |
@@ -611,49 +538,17 @@ jobs:
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
export ANDROID_NDK="${ANDROID_SDK_ROOT}/ndk-bundle"
export ANDROID_NDK_ROOT="${ANDROID_NDK}"
cd src
echo "#define STRAVA_SECRET_KEY ${{ secrets.strava_secret_key }}" > secret.h
echo "#define SMTP_USERNAME ${{ secrets.smtp_username }}" >> secret.h
echo "#define SMTP_PASSWORD ${{ secrets.smtp_password }}" >> secret.h
echo "#define SMTP_SERVER ${{ secrets.smtp_server }}" >> secret.h
echo "${{ secrets.cesiumkey }}" >> inner_templates/googlemaps/cesium-key.js
echo "#define LICENSE" >> secret.h
cd ..
ln -sfn $ANDROID_SDK_ROOT/ndk/21.4.7075529 $ANDROID_NDK
rm -rf /usr/local/lib/android/sdk/ndk/25.1.8937393
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
- name: Archive apk binary
uses: actions/upload-artifact@v2
with:
name: fdroid-android-trial
path: ${{ github.workspace }}/output/android/build/outputs/apk/debug/
# - name: Exit if not on master branch
# if: github.ref == 'refs/heads/main'
# run: exit 1
# - name: upload windows artifact
# uses: actions/upload-release-asset@v1
# env:
# GITHUB_TOKEN: ${{ github.token }}
# with:
# upload_url: ${{ steps.create_release.outputs.upload_url }}
# asset_path: ${{ github.workspace }}/output/android/build/outputs/apk/debug/android-debug.apk
# asset_name: fdroid-android-trial.zip
# asset_content_type: application/zip
ios-build:
# The type of runner that the job will run on
runs-on: macos-latest
permissions:
contents: write
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
@@ -705,342 +600,5 @@ jobs:
run: cp qt-patches/ios/5.15.2/binary/*.* ${{ github.workspace }}/output/ios/Qt/5.15.2/ios/lib/
- name: Build
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 ..
qmake CONFIG+=debug && make -j4
run: qmake CONFIG+=debug && make -j4
# causes iOS build on Mac to fail
# - name: Commit moc files
# uses: EndBug/add-and-commit@v9
# with:
# message: 'moc files added'
# add: 'src/moc_*.cpp --force'
# if: github.ref == 'refs/heads/master'
window-msvc2019-build:
runs-on: windows-latest
strategy:
matrix:
config:
- {python: true}
- {python: false}
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"
- uses: actions/setup-python@v4
with:
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
if: matrix.config.python
- 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: |
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/*.py .
cp ../../windows/*.bat .
cp ../../../windows_openssl/*.* .
mkdir adb
mkdir python
Copy-Item -Path C:\hostedtoolcache\windows\Python\3.7.9\x64 -Destination python -Recurse
cp ../../adb/* adb/
cd ..
cd appx
#../../MSIX-Toolkit/WindowsSDK/10/10.0.20348.0/x64/makeappx.exe pack /d ../output/ /p qz
if: matrix.config.python
- name: Build without python
run: |
qmake
nmake
cd src/debug
mkdir output
mkdir appx
cp qdomyos-zwift.exe output/
cd output
windeployqt --qmldir ../../ qdomyos-zwift.exe
cp "C:/mingw64/bin/libwinpthread-1.dll" .
cp "C:/mingw64/bin/libgcc_s_seh-1.dll" .
cp "C:/mingw64/bin/libstdc++-6.dll" .
cp ../../../icons/iOS/iTunesArtwork@2x.png .
cp ../../AppxManifest.xml .
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
if: matrix.config.python == false
- 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-binary.zip
if: matrix.config.python
- name: Zip artifact for deployment
run: Compress-Archive src/debug/output windows-msvc2019-binary-no-python.zip
if: ${{ ! matrix.config.python }}
- name: Archive windows binary
uses: actions/upload-artifact@v2
with:
name: windows-msvc2019-binary
path: windows-msvc2019-binary.zip
if: matrix.config.python
- name: Archive windows binary
uses: actions/upload-artifact@v2
with:
name: windows-msvc2019-binary-no-python
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
if: github.event_name == 'schedule'
needs: [linux-x86-build, window-msvc2019-build, ios-build, window-build, android-build] # Specify the job dependencies
steps:
- name: Download artifacts
uses: actions/download-artifact@v3
- name: Update nightly release
uses: andelf/nightly-release@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: nightly
prerelease: false
name: 'QZ nightly build $$'
body: |
This is a nightly build of QZ.
You can use this if you want to try new features without waiting for releases.
From time to time, in development builds, old difficult-to-reproduce bugs are
fixed, but it is also true that in the development process with the introduction
of new complex code, the stability of the program may suffer compared to
official releases, so **use it with caution**!
__Please help us improve QZ by reporting any issues you encounter!__ :wink:
files: |
windows-msvc2019-binary-no-python/*
windows-msvc2019-binary/*
windows-msvc2019-ai-server-binary/*
windows-binary-no-python/*
windows-binary/*
fdroid-android-trial/*

1
.gitignore vendored
View File

@@ -49,4 +49,3 @@ src/inner_templates/googlemaps/cesium-key.js
*.autosave
.vscode/settings.json
/tst/Devices/.vs
src/inner_templates/googlemaps/cesium-key.js

3
.gitmodules vendored
View File

@@ -13,6 +13,3 @@
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

112
README.md
View File

@@ -7,99 +7,35 @@ Zwift bridge for Treadmills and Bike!
[<img src="docs/img/app_store.png">](https://apps.apple.com/app/id1543684531?fbclid=IwAR10H6y3mEgwkTlGJON3e8voYOh2wt3kLFOpFzoIXaYZ_N0y0pDvKxHMUaM)
<a href="https://www.buymeacoffee.com/cagnulein" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
<table>
<tr>
<td>
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot1.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
</td>
<td>
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot2.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
</td>
<td>
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot3.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
</td>
<td>
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot4.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
</td>
<td>
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot5.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
</td>
</tr>
</table>
![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
# 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||
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
![First Success](docs/img/first_success.jpg)
### Installation
You can install it on multiple platforms.
You can install on multiple platforms.
Read the [installation procedure](docs/10_Installation.md)
@@ -109,7 +45,7 @@ You can run the app on [Macintosh or Linux devices](docs/10_Installation.md). IO
QDomyos-Zwift works on every [FTMS-compatible application](docs/20_supported_devices_and_applications.md), and virtually any [bluetooth enabled device](docs/20_supported_devices_and_applications.md).
### No GUI version
### No gui version
run as
@@ -121,7 +57,7 @@ https://github.com/ProH4Ck/treadmill-bridge
https://www.livestrong.com/article/422012-what-is-10-degrees-in-incline-on-a-treadmill/
Icons used in this documentation come from [flaticon.com](https://www.flaticon.com)
Icons used in this documentation comes from [flaticon.com](https://www.flaticon.com)
### Blog

View File

@@ -2,4 +2,3 @@
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "swiftDebug.h"

View File

@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 52;
objects = {
/* Begin PBXAggregateTarget section */
@@ -114,9 +114,6 @@
7EC1321DD83EAAFAA2B7109C /* domyosbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 7944A61A6F17291731CE6F84 /* domyosbike.cpp */; settings = {ATTRIBUTES = (); }; };
8556B13A3D02D52A21FC5E3E /* bluetooth.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = B0BE11FB9531A6AD480B20E7 /* bluetooth.cpp */; settings = {ATTRIBUTES = (); }; };
868B65D0AB5114A4A0D5479E /* qmldbg_messages in Link Binary With Libraries */ = {isa = PBXBuildFile; fileRef = 008F20821C7E4D5F7DB55754 /* qmldbg_messages */; };
8701142A2B14D5A800193FC6 /* moc_eliteariafan.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 870114292B14D5A800193FC6 /* moc_eliteariafan.cpp */; };
8701142D2B14D5C600193FC6 /* eliteariafan.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8701142C2B14D5C600193FC6 /* eliteariafan.cpp */; };
870114302B14D5F400193FC6 /* ios_eliteariafan.mm in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8701142E2B14D5F400193FC6 /* ios_eliteariafan.mm */; };
8703BAEB273C67A90058E206 /* pafersbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8703BAE9273C67A90058E206 /* pafersbike.cpp */; };
8703BAED273C67B60058E206 /* moc_pafersbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 8703BAEC273C67B50058E206 /* moc_pafersbike.cpp */; };
87061390286D8B4F00D2446E /* libQt5PositioningQuick.a in Link Binary With Libraries */ = {isa = PBXBuildFile; fileRef = 8706138F286D8B4F00D2446E /* libQt5PositioningQuick.a */; };
@@ -173,10 +170,6 @@
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 */; };
@@ -261,16 +254,11 @@
87433F2127D8B722003D1672 /* simplecrypt.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87433F2027D8B722003D1672 /* simplecrypt.cpp */; };
87440FBD2640291700E4DC0B /* fitplusbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87440FBC2640291700E4DC0B /* fitplusbike.cpp */; };
87440FBF2640292900E4DC0B /* moc_fitplusbike.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87440FBE2640292900E4DC0B /* moc_fitplusbike.cpp */; };
8745B2762AFCB4A300991A39 /* android in Copy Bundle Resources */ = {isa = PBXBuildFile; fileRef = 8745B2752AFCB4A300991A39 /* android */; };
8745B2782AFCB87B00991A39 /* libadb.a in Link Binary With Libraries */ = {isa = PBXBuildFile; fileRef = 8745B2742AFCB3B300991A39 /* libadb.a */; };
87473A9627ECA9EE00C203F5 /* proformrower.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87473A9527ECA9EE00C203F5 /* proformrower.cpp */; };
87473A9827ECAA0500C203F5 /* moc_proformrower.cpp in Compile Sources */ = {isa = PBXBuildFile; fileRef = 87473A9727ECAA0500C203F5 /* moc_proformrower.cpp */; };
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 */; };
@@ -374,7 +362,6 @@
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 */; };
@@ -827,11 +814,6 @@
867187CB3CB3703D1925C88A /* fit_weather_conditions_mesg_listener.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = fit_weather_conditions_mesg_listener.hpp; path = "/Users/cagnulein/qdomyos-zwift/src/fit-sdk/fit_weather_conditions_mesg_listener.hpp"; sourceTree = "<absolute>"; };
86DD72842A64993F31E31719 /* fit_ant_rx_mesg_listener.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = fit_ant_rx_mesg_listener.hpp; path = "/Users/cagnulein/qdomyos-zwift/src/fit-sdk/fit_ant_rx_mesg_listener.hpp"; sourceTree = "<absolute>"; };
86F10E1AE2D47520E65C0543 /* fit_dive_summary_mesg_listener.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = fit_dive_summary_mesg_listener.hpp; path = "/Users/cagnulein/qdomyos-zwift/src/fit-sdk/fit_dive_summary_mesg_listener.hpp"; sourceTree = "<absolute>"; };
870114292B14D5A800193FC6 /* moc_eliteariafan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_eliteariafan.cpp; sourceTree = "<group>"; };
8701142B2B14D5C600193FC6 /* eliteariafan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eliteariafan.h; path = ../src/eliteariafan.h; sourceTree = "<group>"; };
8701142C2B14D5C600193FC6 /* eliteariafan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = eliteariafan.cpp; path = ../src/eliteariafan.cpp; sourceTree = "<group>"; };
8701142E2B14D5F400193FC6 /* ios_eliteariafan.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_eliteariafan.mm; path = ../src/ios/ios_eliteariafan.mm; sourceTree = "<group>"; };
8701142F2B14D5F400193FC6 /* ios_eliteariafan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ios_eliteariafan.h; path = ../src/ios/ios_eliteariafan.h; sourceTree = "<group>"; };
8703BAE9273C67A90058E206 /* pafersbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pafersbike.cpp; path = ../src/pafersbike.cpp; sourceTree = "<group>"; };
8703BAEA273C67A90058E206 /* pafersbike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pafersbike.h; path = ../src/pafersbike.h; sourceTree = "<group>"; };
8703BAEC273C67B50058E206 /* moc_pafersbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_pafersbike.cpp; sourceTree = "<group>"; };
@@ -899,13 +881,6 @@
8727A47527849EA600019B5D /* paferstreadmill.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = paferstreadmill.h; path = ../src/paferstreadmill.h; sourceTree = "<group>"; };
8727A47627849EA600019B5D /* paferstreadmill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = paferstreadmill.cpp; path = ../src/paferstreadmill.cpp; sourceTree = "<group>"; };
8727A47827849EB200019B5D /* moc_paferstreadmill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_paferstreadmill.cpp; sourceTree = "<group>"; };
8727C7CC2B3BF1B8005429EB /* proformtelnetbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = proformtelnetbike.cpp; path = ../src/proformtelnetbike.cpp; sourceTree = "<group>"; };
8727C7CD2B3BF1B8005429EB /* proformtelnetbike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = proformtelnetbike.h; path = ../src/proformtelnetbike.h; sourceTree = "<group>"; };
8727C7CE2B3BF1B8005429EB /* QTelnet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QTelnet.h; path = ../src/QTelnet.h; sourceTree = "<group>"; };
8727C7CF2B3BF1B8005429EB /* QTelnet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = QTelnet.cpp; path = ../src/QTelnet.cpp; sourceTree = "<group>"; };
8727C7D22B3BF1E4005429EB /* moc_QTelnet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_QTelnet.cpp; sourceTree = "<group>"; };
8727C7D32B3BF1E4005429EB /* moc_proformtelnetbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_proformtelnetbike.cpp; sourceTree = "<group>"; };
8729149E2B2B010600565E33 /* qdomyoszwift-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "qdomyoszwift-Bridging-Header.h"; sourceTree = "<group>"; };
872A20D828C5EC380037774D /* faketreadmill.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = faketreadmill.h; path = ../src/faketreadmill.h; sourceTree = "<group>"; };
872A20D928C5EC380037774D /* faketreadmill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = faketreadmill.cpp; path = ../src/faketreadmill.cpp; sourceTree = "<group>"; };
872A20DB28C5F5CE0037774D /* moc_faketreadmill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_faketreadmill.cpp; sourceTree = "<group>"; };
@@ -1031,9 +1006,6 @@
87440FBB2640291700E4DC0B /* fitplusbike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fitplusbike.h; path = ../src/fitplusbike.h; sourceTree = "<group>"; };
87440FBC2640291700E4DC0B /* fitplusbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fitplusbike.cpp; path = ../src/fitplusbike.cpp; sourceTree = "<group>"; };
87440FBE2640292900E4DC0B /* moc_fitplusbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_fitplusbike.cpp; sourceTree = "<group>"; };
8745B2742AFCB3B300991A39 /* libadb.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libadb.a; path = ../src/ios/libadb.a; sourceTree = "<group>"; };
8745B2752AFCB4A300991A39 /* android */ = {isa = PBXFileReference; lastKnownFileType = folder; name = android; path = ../src/ios/android; sourceTree = "<group>"; };
8745B2772AFCB52800991A39 /* AdbClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AdbClient.h; path = ../src/ios/AdbClient.h; sourceTree = "<group>"; };
87473A9427ECA9EE00C203F5 /* proformrower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = proformrower.h; path = ../src/proformrower.h; sourceTree = "<group>"; };
87473A9527ECA9EE00C203F5 /* proformrower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = proformrower.cpp; path = ../src/proformrower.cpp; sourceTree = "<group>"; };
87473A9727ECAA0500C203F5 /* moc_proformrower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_proformrower.cpp; sourceTree = "<group>"; };
@@ -1041,11 +1013,6 @@
874D271F29AFA11F0007C079 /* apexbike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = apexbike.h; path = ../src/apexbike.h; sourceTree = "<group>"; };
874D272129AFA13B0007C079 /* moc_apexbike.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_apexbike.cpp; sourceTree = "<group>"; };
8752B4CC27F43D9200E2EC6C /* qz.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = qz.storekit; sourceTree = "<group>"; };
8752C0E22B15D84100C3D1A5 /* moc_eliteariafan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_eliteariafan.cpp; sourceTree = "<group>"; };
8752C0E42B15D85600C3D1A5 /* eliteariafan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = eliteariafan.cpp; path = ../src/eliteariafan.cpp; sourceTree = "<group>"; };
8752C0E52B15D85600C3D1A5 /* eliteariafan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = eliteariafan.h; path = ../src/eliteariafan.h; sourceTree = "<group>"; };
8752C0E62B15D85600C3D1A5 /* ios_eliteariafan.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ios_eliteariafan.mm; path = ../src/ios/ios_eliteariafan.mm; sourceTree = "<group>"; };
8752C0E72B15D85600C3D1A5 /* ios_eliteariafan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ios_eliteariafan.h; path = ../src/ios/ios_eliteariafan.h; sourceTree = "<group>"; };
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 = "<group>"; };
8754D24B27F786F0003D7054 /* virtualrower.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = virtualrower.swift; path = ../src/ios/virtualrower.swift; sourceTree = "<group>"; };
87586A3F25B8340D00A243C4 /* proformbike.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = proformbike.h; path = ../src/proformbike.h; sourceTree = "<group>"; };
@@ -1201,8 +1168,6 @@
87A18F052660D5C0002D7C96 /* ftmsrower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ftmsrower.cpp; path = ../src/ftmsrower.cpp; sourceTree = "<group>"; };
87A18F062660D5C1002D7C96 /* ftmsrower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ftmsrower.h; path = ../src/ftmsrower.h; sourceTree = "<group>"; };
87A18F082660D5D9002D7C96 /* moc_ftmsrower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = moc_ftmsrower.cpp; sourceTree = "<group>"; };
87A2E0202B2B024200E6168F /* swiftDebug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = swiftDebug.h; path = ../src/ios/swiftDebug.h; sourceTree = "<group>"; };
87A2E0212B2B053E00E6168F /* swiftDebug.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = swiftDebug.mm; path = ../src/ios/swiftDebug.mm; sourceTree = "<group>"; };
87A3BC1E2656429300D302E3 /* echelonrower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = echelonrower.h; path = ../src/echelonrower.h; sourceTree = "<group>"; };
87A3BC1F2656429400D302E3 /* rower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = rower.cpp; path = ../src/rower.cpp; sourceTree = "<group>"; };
87A3BC202656429400D302E3 /* echelonrower.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = echelonrower.cpp; path = ../src/echelonrower.cpp; sourceTree = "<group>"; };
@@ -1599,7 +1564,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8745B2782AFCB87B00991A39 /* libadb.a in Link Binary With Libraries */,
879F74112893D5B8009A64C8 /* libqavfcamera.a in Link Binary With Libraries */,
879F740F2893D592009A64C8 /* libqtmedia_audioengine.a in Link Binary With Libraries */,
879F740C2893D4FA009A64C8 /* libqtaudio_coreaudio.a in Link Binary With Libraries */,
@@ -1925,20 +1889,6 @@
2EB56BE3C2D93CDAB0C52E67 /* Sources */ = {
isa = PBXGroup;
children = (
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 */,
878D83732A1F33C600D7F004 /* bkoolbike.cpp */,
@@ -2296,7 +2246,6 @@
35E903698E72424585D33829 /* virtualtreadmill.h */,
C8CE72E7B224D8B886614E3F /* domyosbike.h */,
8710707229C4A5E70094D0F3 /* GarminConnect.swift */,
87A2E0202B2B024200E6168F /* swiftDebug.h */,
);
name = Sources;
sourceTree = "<group>";
@@ -2389,7 +2338,6 @@
AF39DD055C3EF8226FBE929D /* Frameworks */ = {
isa = PBXGroup;
children = (
8745B2742AFCB3B300991A39 /* libadb.a */,
873D388A29B0D744006A2611 /* ConnectIQ.xcframework */,
879F74142893D732009A64C8 /* CoreMedia.framework */,
879F74122893D705009A64C8 /* CoreVideo.framework */,
@@ -2779,7 +2727,6 @@
E8C543AB96796ECAA2E65C57 /* qdomyoszwift */ = {
isa = PBXGroup;
children = (
8745B2752AFCB4A300991A39 /* android */,
8752B4CC27F43D9200E2EC6C /* qz.storekit */,
2EB56BE3C2D93CDAB0C52E67 /* Sources */,
25B08E2869634E9BCBA333A2 /* Generated Sources */,
@@ -2916,7 +2863,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8745B2762AFCB4A300991A39 /* android in Copy Bundle Resources */,
87C5F0BC26285E5F0067A1B5 /* SmtpMime in Copy Bundle Resources */,
2188AA0A52E9CD610922F82E /* Default-568h@2x.png in Copy Bundle Resources */,
8752B4CD27F43D9200E2EC6C /* qz.storekit in Copy Bundle Resources */,
@@ -3039,8 +2985,6 @@
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 */,
@@ -3048,10 +2992,8 @@
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 */,
@@ -3185,7 +3127,6 @@
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 */,
@@ -3287,7 +3228,6 @@
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 */,
@@ -3336,7 +3276,6 @@
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 */,
@@ -3368,7 +3307,6 @@
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 */,
@@ -3728,7 +3666,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 693;
CURRENT_PROJECT_VERSION = 612;
DEVELOPMENT_TEAM = 6335M7T29D;
ENABLE_BITCODE = NO;
HEADER_SEARCH_PATHS = (
@@ -3802,9 +3740,8 @@
/Users/cagnulein/Qt/5.15.2/ios/plugins/mediaservice,
/Users/cagnulein/Qt/5.15.2/ios/plugins/playlistformats,
/Users/cagnulein/Qt/5.15.2/ios/plugins/audio,
"/Users/cagnulein/qdomyos-zwift/src/ios",
);
MARKETING_VERSION = 2.16;
MARKETING_VERSION = 2.13;
OTHER_CFLAGS = (
"-pipe",
"-g",
@@ -3881,7 +3818,6 @@
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;
@@ -3898,7 +3834,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 693;
CURRENT_PROJECT_VERSION = 612;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 6335M7T29D;
ENABLE_BITCODE = NO;
@@ -3974,9 +3910,8 @@
/Users/cagnulein/Qt/5.15.2/ios/plugins/mediaservice,
/Users/cagnulein/Qt/5.15.2/ios/plugins/playlistformats,
/Users/cagnulein/Qt/5.15.2/ios/plugins/audio,
"/Users/cagnulein/qdomyos-zwift/src/ios",
);
MARKETING_VERSION = 2.16;
MARKETING_VERSION = 2.13;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"-pipe",
@@ -4054,7 +3989,6 @@
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;
@@ -4104,7 +4038,7 @@
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 693;
CURRENT_PROJECT_VERSION = 612;
DEVELOPMENT_TEAM = 6335M7T29D;
ENABLE_BITCODE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -4129,7 +4063,7 @@
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MARKETING_VERSION = 2.16;
MARKETING_VERSION = 2.13;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
OTHER_CODE_SIGN_FLAGS = "--generate-entitlement-der";
@@ -4200,7 +4134,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 693;
CURRENT_PROJECT_VERSION = 612;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 6335M7T29D;
ENABLE_BITCODE = YES;
@@ -4221,7 +4155,7 @@
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
MARKETING_VERSION = 2.16;
MARKETING_VERSION = 2.13;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
OTHER_CODE_SIGN_FLAGS = "--generate-entitlement-der";
@@ -4292,7 +4226,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 693;
CURRENT_PROJECT_VERSION = 612;
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
ENABLE_BITCODE = YES;
ENABLE_PREVIEWS = YES;
@@ -4337,7 +4271,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.16;
MARKETING_VERSION = 2.13;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
OTHER_CODE_SIGN_FLAGS = "--generate-entitlement-der";
@@ -4406,7 +4340,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 693;
CURRENT_PROJECT_VERSION = 612;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
ENABLE_BITCODE = YES;
@@ -4447,7 +4381,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 2.16;
MARKETING_VERSION = 2.13;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
OTHER_CODE_SIGN_FLAGS = "--generate-entitlement-der";

View File

@@ -104,9 +104,6 @@ extension MainController: WorkoutTrackingDelegate {
"\(heartRate)" as AnyObject])
WorkoutTracking.distance = WatchKitConnection.distance
WorkoutTracking.kcal = WatchKitConnection.kcal
WorkoutTracking.speed = WatchKitConnection.speed
WorkoutTracking.power = WatchKitConnection.power
WorkoutTracking.cadence = WatchKitConnection.cadence
if Locale.current.measurementSystem != "Metric" {
self.distanceLabel.setText("Distance \(String(format:"%.2f", WorkoutTracking.distance))")

View File

@@ -24,9 +24,6 @@ class WatchKitConnection: NSObject {
public static var distance = 0.0
public static var kcal = 0.0
public static var stepCadence = 0
public static var speed = 0.0
public static var cadence = 0.0
public static var power = 0.0
weak var delegate: WatchKitConnectionDelegate?
private override init() {
@@ -69,13 +66,6 @@ extension WatchKitConnection: WatchKitConnectionProtocol {
WatchKitConnection.distance = dDistance
let dKcal = Double(result["kcal"] as! Double)
WatchKitConnection.kcal = dKcal
let dSpeed = Double(result["speed"] as! Double)
WatchKitConnection.speed = dSpeed
let dPower = Double(result["power"] as! Double)
WatchKitConnection.power = dPower
let dCadence = Double(result["cadence"] as! Double)
WatchKitConnection.cadence = dCadence
}, errorHandler: { (error) in
print(error)
})

View File

@@ -31,10 +31,6 @@ class WorkoutTracking: NSObject {
public static var cadenceTimeStamp = NSDate().timeIntervalSince1970
public static var cadenceLastSteps = Double()
public static var cadenceSteps = 0
public static var speed = Double()
public static var power = Double()
public static var cadence = Double()
public static var lastDateMetric = Date()
var sport: Int = 0
let healthStore = HKHealthStore()
let configuration = HKWorkoutConfiguration()
@@ -150,37 +146,14 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
HKSampleType.workoutType()
])
var infoToShare: Set<HKSampleType> = []
if #available(watchOSApplicationExtension 10.0, *) {
infoToShare = Set([
HKSampleType.quantityType(forIdentifier: .stepCount)!,
HKSampleType.quantityType(forIdentifier: .heartRate)!,
HKSampleType.quantityType(forIdentifier: .distanceCycling)!,
HKSampleType.quantityType(forIdentifier: .distanceWalkingRunning)!,
HKSampleType.quantityType(forIdentifier: .activeEnergyBurned)!,
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 {
// Fallback on earlier versions
infoToShare = Set([
HKSampleType.quantityType(forIdentifier: .stepCount)!,
HKSampleType.quantityType(forIdentifier: .heartRate)!,
HKSampleType.quantityType(forIdentifier: .distanceCycling)!,
HKSampleType.quantityType(forIdentifier: .distanceWalkingRunning)!,
HKSampleType.quantityType(forIdentifier: .activeEnergyBurned)!,
HKSampleType.workoutType()
])
}
let infoToShare = Set([
HKSampleType.quantityType(forIdentifier: .stepCount)!,
HKSampleType.quantityType(forIdentifier: .heartRate)!,
HKSampleType.quantityType(forIdentifier: .distanceCycling)!,
HKSampleType.quantityType(forIdentifier: .distanceWalkingRunning)!,
HKSampleType.quantityType(forIdentifier: .activeEnergyBurned)!,
HKSampleType.workoutType()
])
HKHealthStore().requestAuthorization(toShare: infoToShare, read: infoToRead) { (success, error) in
if success {
@@ -195,7 +168,6 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
}
func startWorkOut() {
WorkoutTracking.lastDateMetric = Date()
print("Start workout")
configWorkout()
workoutSession.startActivity(with: Date())
@@ -340,135 +312,6 @@ extension WorkoutTracking: HKLiveWorkoutBuilderDelegate {
handleSendStatisticsData(statistics)
}
}
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
}
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 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: .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
}
}
WorkoutTracking.lastDateMetric = Date()
}
func workoutBuilderDidCollectEvent(_ workoutBuilder: HKLiveWorkoutBuilder) {

View File

@@ -28,7 +28,7 @@ $ sudo ./qdomyos-zwift
You will need to (at a minimum) to install the xcode Command Line Tools (CLI) thanks to @richardwait
https://developer.apple.com/download/more/?=xcode
Download and install https://download.qt.io/archive/qt/5.12/5.12.12/qt-opensource-mac-x64-5.12.12.dmg and simply run the qdomyos-zwift release for MacOs
Download and install http://download.qt.io/official_releases/qt/5.12/5.12.9/qt-opensource-mac-x64-5.12.9.dmg and simply run the qdomyos-zwift release for MacOs
## On Raspberry Pi Zero W
@@ -77,7 +77,7 @@ Apply the changes `sudo systemctl restart dhcpcd.service` and ensure you have in
#### Enable SSH access
You might want to access your raspberry remotely while it is attached to your fitness equipment.
You might want to access your raspberry remotely while it is attached to your fitness equipement.
`sudo raspi-config` > `Interface Options` > `SSH`
@@ -175,7 +175,7 @@ Then reboot to check operations (`sudo reboot`)
### (optional) Enable overlay FS
Once that everything is working as expected, and if you dedicate your Raspberry pi to this usage, you might want to enable the read-only overlay FS.
Once that everything is working as expected, and if you dedicate your raspeberry pi to this usage, you might want to enable the read-only overlay FS.
By enabling the overlay read-only system, your SD card will be read-only only and every file written will be to RAM.
Then at each reboot the RAM is erased and you'll revert to the initial status of the overlay file-system.

View File

@@ -18,7 +18,7 @@ Please refer to this article for more information under [QML Operations](https:/
## Configuration in NativeQT mode
This is the list of settings available in the application. These settings need to be appended to the binary command line.
This is the list of settings available in the application. These settings needs to be appended to the binary command line.
*Example :* `sudo ./qdomyos-zwift -no-gui` for disabling any graphical interface.
| **Option** | **Type** | **Default** | **Function** |
@@ -35,8 +35,8 @@ This is the list of settings available in the application. These settings need t
| -heart-service | Boolean | True | Simulate HR service (required for applications not reading FTMS) |
| -only-virtualbike | Boolean | False | |
| -only-virtualtreadmill | Boolean | False | |
| -no-reconnection | Boolean | False | QZ will not try to reconnect your fitness equipment if enabled |
| -bluetooth-relaxed | Boolean | False | In case of deconnections from QZ to your fitness equipment |
| -no-reconnection | Boolean | False | QZ will not try to reconnect your fitness equipement if enabled |
| -bluetooth-relaxed | Boolean | False | In case of deconnections from QZ to your fitness equipement |
| -bike-cadence-sensor | Boolean | False | |
| -bike-power-sensor | Boolean | False | |
| -battery-service | Boolean | False | |
@@ -45,7 +45,7 @@ This is the list of settings available in the application. These settings need t
| -run-cadence-sensor | Boolean | False | |
| -nordictrack-10-treadmill | Boolean | False | Enable NordicTrack compatibility mode |
| -train | String | | Force training program |
| -name | String | | Force bluetooth device name (if QZ struggles to find your fitness equipment) |
| -name | String | | Force bluetooth device name (if QZ struggles finding your fitness equipment) |
| -poll-device-time | Int | 200 (ms) | Frequency to refresh information from QZ to Fitness equipment |
| -bike-resistance-gain | Int | | Adjust resistance from the fitness application |
| -bike-resistance-offset | Int | | Set another resistance point than default |

View File

@@ -1,5 +0,0 @@
QMAKE_PRL_BUILD_DIR = C:/qt-everywhere-src-5.15.2/qtconnectivity/src/bluetooth
QMAKE_PRO_INPUT = bluetooth.pro
QMAKE_PRL_TARGET = Qt5Bluetooth.lib
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin windows prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl flat debug_and_release precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe shared shared release no_plugin_manifest win32 msvc copy_dir_files sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd rdseed shani x86SimdAlways prefix_build force_independent utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions release ReleaseBuild Release build_pass c++11 generated_privates relative_qt_rpath target_qt c++11 strict_c++ c++14 c++1z qt_install_headers need_fwd_pri qt_install_module debug_and_release build_all create_cmake skip_target_version_ext release ReleaseBuild Release build_pass have_target dll exclusive_builds debug_info no_autoqmake thread moc resources
QMAKE_PRL_VERSION = 5.15.2

View File

@@ -1,5 +0,0 @@
QMAKE_PRL_BUILD_DIR = C:/qt-everywhere-src-5.15.2/qtconnectivity/src/bluetooth
QMAKE_PRO_INPUT = bluetooth.pro
QMAKE_PRL_TARGET = Qt5Bluetoothd.lib
QMAKE_PRL_CONFIG = lex yacc debug depend_includepath testcase_targets import_plugins import_qpa_plugin windows prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on link_prl flat debug_and_release precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe shared shared no_plugin_manifest win32 msvc copy_dir_files sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd rdseed shani x86SimdAlways prefix_build force_independent utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions debug DebugBuild Debug build_pass c++11 generated_privates relative_qt_rpath target_qt c++11 strict_c++ c++14 c++1z qt_install_headers need_fwd_pri qt_install_module debug_and_release build_all create_cmake skip_target_version_ext debug DebugBuild Debug build_pass have_target dll no_plist exclusive_builds debug_info no_autoqmake thread moc resources
QMAKE_PRL_VERSION = 5.15.2

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +0,0 @@
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.0
import Qt.labs.settings 1.0
ColumnLayout {
anchors.fill: parent
Loader {
id: chartFooterLoader
sourceComponent: ChartFooterInnerJS
anchors.fill: parent
active: false
}
Loader {
anchors.fill: parent
source: CHARTJS ? "ChartFooterInnerJS.qml":"ChartFooterInnerNoJS.qml"
onLoaded: {
if(CHARTJS) {
chartFooterLoader.active = true;
}
}
}
}

View File

@@ -1,31 +0,0 @@
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.0
import Qt.labs.settings 1.0
import QtWebView 1.1
ColumnLayout {
anchors.fill: parent
Settings {
id: settings
}
WebView {
id: webView
anchors.fill: parent
url: "http://localhost:" + settings.value("template_inner_QZWS_port") + "/chartjs/chartlive.htm"
visible: rootItem.chartFooterVisible
onLoadingChanged: {
if (loadRequest.errorString) {
console.error(loadRequest.errorString);
console.error("port " + settings.value("template_inner_QZWS_port"));
}
}
onVisibleChanged: {
console.log("onVisibleChanged" + visible)
if(visible === true) {
reload();
}
}
}
}

View File

@@ -1,12 +0,0 @@
import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.0
import Qt.labs.settings 1.0
ColumnLayout {
anchors.fill: parent
Settings {
id: settings
}
}

View File

@@ -37,9 +37,12 @@
#include <QThread>
#ifdef WIN32
#include <windows.h>
#include <windef.h>
#endif
#ifdef WIN32
#include <winbase.h>
#include <windows.h>
#else
#include <sys/ioctl.h>
#include <termios.h> // unix!!

View File

@@ -11,7 +11,6 @@ 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
@@ -19,11 +18,7 @@ ColumnLayout {
folder: shortcuts.home
onAccepted: {
console.log("You chose: " + fileDialogTrainProgram.fileUrl)
if(OS_VERSION === "Android") {
trainprogram_open_other_folder(fileDialogTrainProgram.fileUrl)
} else {
trainprogram_open_clicked(fileDialogTrainProgram.fileUrl)
}
trainprogram_open_clicked(fileDialogTrainProgram.fileUrl)
fileDialogTrainProgram.close()
}
onRejected: {

View File

@@ -291,75 +291,59 @@ HomeForm{
}
footer:
Item {
width: parent.width
height: (rootItem.chartFooterVisible ? parent.height / 4 : parent.height / 2)
Rectangle {
objectName: "footerrectangle"
visible: rootItem.videoVisible
anchors.top: gridView.bottom
visible: rootItem.chartFooterVisible || rootItem.videoVisible
width: parent.width
height: parent.height / 2
// Removed Timer, Play/Pause/Resume is now done via Homeform.cpp
/*
Timer {
id: pauseTimer
interval: 1000; running: true; repeat: true
onTriggered: { if(visible == true) { (rootItem.currentSpeed > 0 ?
videoPlaybackHalf.play() :
videoPlaybackHalf.pause()) } }
}
*/
Rectangle {
id: chartFooterRectangle
visible: rootItem.chartFooterVisible
anchors.fill: parent
ChartFooter {
anchors.fill: parent
visible: rootItem.chartFooterVisible
onVisibleChanged: {
if(visible === true) {
console.log("mediaPlayer onCompleted: " + rootItem.videoPath)
console.log("videoRate: " + rootItem.videoRate)
videoPlaybackHalf.source = rootItem.videoPath
//videoPlaybackHalf.playbackRate = rootItem.videoRate
videoPlaybackHalf.seek(rootItem.videoPosition)
videoPlaybackHalf.play()
videoPlaybackHalf.muted = rootItem.currentCoordinateValid
} else {
videoPlaybackHalf.stop()
}
}
Rectangle {
objectName: "footerrectangle"
visible: rootItem.videoVisible
anchors.fill: parent
// Removed Timer, Play/Pause/Resume is now done via Homeform.cpp
/*
Timer {
id: pauseTimer
interval: 1000; running: true; repeat: true
onTriggered: { if(visible == true) { (rootItem.currentSpeed > 0 ?
videoPlaybackHalf.play() :
videoPlaybackHalf.pause()) } }
}
*/
MediaPlayer {
id: videoPlaybackHalf
objectName: "videoplaybackhalf"
autoPlay: false
playbackRate: rootItem.videoRate
onVisibleChanged: {
if(visible === true) {
console.log("mediaPlayer onCompleted: " + rootItem.videoPath)
console.log("videoRate: " + rootItem.videoRate)
videoPlaybackHalf.source = rootItem.videoPath
//videoPlaybackHalf.playbackRate = rootItem.videoRate
videoPlaybackHalf.seek(rootItem.videoPosition)
videoPlaybackHalf.play()
videoPlaybackHalf.muted = rootItem.currentCoordinateValid
} else {
videoPlaybackHalf.stop()
}
}
MediaPlayer {
id: videoPlaybackHalf
objectName: "videoplaybackhalf"
autoPlay: false
playbackRate: rootItem.videoRate
onError: {
if (videoPlaybackHalf.NoError !== error) {
console.log("[qmlvideo] VideoItem.onError error " + error + " errorString " + errorString)
}
onError: {
if (videoPlaybackHalf.NoError !== error) {
console.log("[qmlvideo] VideoItem.onError error " + error + " errorString " + errorString)
}
}
VideoOutput {
id:videoPlayer
anchors.fill: parent
source: videoPlaybackHalf
}
}
}
}
VideoOutput {
id:videoPlayer
anchors.fill: parent
source: videoPlaybackHalf
}
}
MouseArea {
property int currentId: -1 // Original position in model

View File

@@ -1,522 +0,0 @@
#include "QTelnet.h"
#include "QTelnet.h"
#include <QHostAddress>
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;
}
}
}

View File

@@ -1,136 +0,0 @@
#ifndef QTELNET_H
#define QTELNET_H
#include <QObject>
#include <qtcpsocket.h>
#include <qsize.h>
#include <QString>
#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

View File

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

View File

@@ -9,7 +9,6 @@ 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
@@ -17,11 +16,7 @@ ColumnLayout {
folder: shortcuts.home
onAccepted: {
console.log("You chose: " + fileDialogTrainProgram.fileUrl)
if(OS_VERSION === "Android") {
trainprogram_open_other_folder(fileDialogTrainProgram.fileUrl)
} else {
trainprogram_open_clicked(fileDialogTrainProgram.fileUrl)
}
trainprogram_open_clicked(fileDialogTrainProgram.fileUrl)
fileDialogTrainProgram.close()
}
onRejected: {

View File

@@ -297,7 +297,6 @@ 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();
@@ -340,12 +339,12 @@ void activiotreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha
settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) /
200.0) /
(60000.0 / ((double)lastTimeCharacteristicChanged.msecsTo(
now)))); //(( (0.048* Output in watts +1.19) * body weight in
QDateTime::currentDateTime())))); //(( (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(now))));
lastTimeCharacteristicChanged = now;
((double)1000.0 / (double)(lastTimeCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))));
lastTimeCharacteristicChanged = QDateTime::currentDateTime();
}
emit debug(QStringLiteral("Current speed: ") + QString::number(speed));

View File

@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<manifest package="org.cagnulen.qdomyoszwift" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionName="2.16.29" android:versionCode="693" android:installLocation="auto">
<manifest package="org.cagnulen.qdomyoszwift" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionName="2.13.98" android:versionCode="614" android:installLocation="auto">
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS -->
@@ -79,19 +79,6 @@
android:name=".ForegroundService"
android:enabled="true"
android:exported="true"></service>
<service
android:name=".WearableMessageListenerService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
<data
android:host="*"
android:pathPrefix="/qz"
android:scheme="wear" />
</intent-filter>
</service>
<service android:name=".ChannelService"></service>
<service android:name=".FloatingWindowGFG" android:enabled="true" android:exported="true"/>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,95 @@
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
`
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
!
"
#
$
%
&
'
(
)
*
+
,
-
.
/

Binary file not shown.

Binary file not shown.

View File

@@ -23,7 +23,7 @@ println(amazon)
dependencies {
compile 'com.rvalerio:fgchecker:1.1.0'
implementation "androidx.core:core-ktx:1.12.0"
implementation "androidx.core:core-ktx:+"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0"
if(amazon == "1") {
@@ -33,6 +33,7 @@ dependencies {
// google play store
implementation 'com.google.android.gms:play-services-mlkit-text-recognition:18.0.2'
}
implementation 'com.github.cagnulein:paddleocr4android:1.2.8e-sdk21'
implementation 'com.google.android.play:core:1.8.2'
@@ -46,7 +47,6 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'com.github.mik3y:usb-serial-for-android:v3.4.6'
androidTestImplementation "com.android.support:support-annotations:28.0.0"
implementation 'com.google.android.gms:play-services-wearable:+'
}
android {
@@ -100,6 +100,17 @@ android {
compileSdkVersion 33
minSdkVersion = 21
targetSdkVersion = 33
externalNativeBuild {
cmake {
cppFlags "-std=c++11 -frtti -fexceptions -Wno-format"
arguments '-DANDROID_PLATFORM=android-21', '-DANDROID_STL=c++_shared' ,"-DANDROID_ARM_NEON=TRUE"
}
}
}
packagingOptions {
exclude 'META-INF/kotlinx_coroutines_core.version'
}
tasks.all { task ->

View File

@@ -27,7 +27,6 @@
<!-- Concept2 PM3,PM4 -->
<usb-device vendor-id="17A4" product-id="0002" />
<usb-device vendor-id="17A4" product-id="0001" />
<!-- CDC driver -->
<usb-device vendor-id="9025" /> <!-- 0x2341 / ......: Arduino -->

View File

@@ -35,13 +35,11 @@ public class Ant {
static boolean speedRequest = false;
static boolean heartRequest = false;
static boolean garminKey = false;
static boolean treadmill = false;
public void antStart(Activity a, boolean SpeedRequest, boolean HeartRequest, boolean GarminKey, boolean Treadmill) {
public void antStart(Activity a, boolean SpeedRequest, boolean HeartRequest, boolean GarminKey) {
Log.v(TAG, "antStart");
speedRequest = SpeedRequest;
heartRequest = HeartRequest;
treadmill = Treadmill;
garminKey = GarminKey;
activity = a;

View File

@@ -35,14 +35,9 @@ public class CSafeRowerUSBHID {
public static void open(Context context) {
Log.d("QZ","CSafeRowerUSBHID open");
hidBridge = new HidBridge(context, 0x0002, 0x17A4);
hidBridge = new HidBridge(context, 0x0002, 0x17A4);
boolean ret = hidBridge.OpenDevice();
Log.d("QZ","hidBridge.OpenDevice " + ret);
if(ret == false) {
hidBridge = new HidBridge(context, 0x0001, 0x17A4);
ret = hidBridge.OpenDevice();
Log.d("QZ","hidBridge.OpenDevice " + ret);
}
hidBridge.StartReadingThread();
Log.d("QZ","hidBridge.StartReadingThread");
}

View File

@@ -50,7 +50,6 @@ public class ChannelService extends Service {
HeartChannelController heartChannelController = null;
PowerChannelController powerChannelController = null;
SpeedChannelController speedChannelController = null;
SDMChannelController sdmChannelController = null;
private ServiceConnection mAntRadioServiceConnection = new ServiceConnection() {
@Override
@@ -105,9 +104,6 @@ public class ChannelService extends Service {
if (null != speedChannelController) {
speedChannelController.speed = speed;
}
if (null != sdmChannelController) {
sdmChannelController.speed = speed;
}
}
void setPower(int power) {
@@ -123,9 +119,6 @@ public class ChannelService extends Service {
if (null != speedChannelController) {
speedChannelController.cadence = cadence;
}
if (null != sdmChannelController) {
sdmChannelController.cadence = cadence;
}
}
int getHeart() {
@@ -148,12 +141,8 @@ public class ChannelService extends Service {
heartChannelController = new HeartChannelController(acquireChannel());
if (Ant.speedRequest) {
if(Ant.treadmill) {
sdmChannelController = new SDMChannelController(acquireChannel());
} else {
powerChannelController = new PowerChannelController(acquireChannel());
speedChannelController = new SpeedChannelController(acquireChannel());
}
powerChannelController = new PowerChannelController(acquireChannel());
speedChannelController = new SpeedChannelController(acquireChannel());
}
}
@@ -164,12 +153,9 @@ public class ChannelService extends Service {
powerChannelController.close();
if (speedChannelController != null)
speedChannelController.close();
if (sdmChannelController != null)
sdmChannelController.close();
heartChannelController = null;
powerChannelController = null;
speedChannelController = null;
sdmChannelController = null;
}
AntChannel acquireChannel() throws ChannelNotAvailableException {

View File

@@ -1,28 +0,0 @@
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;
}
}

View File

@@ -49,9 +49,6 @@ public class QZAdbRemote implements DeviceConnectionListener {
private static QZAdbRemote INSTANCE;
private static String receiveBuffer = "";
private static String receiveOldBuffer = "";
public static QZAdbRemote getInstance() {
if(INSTANCE == null) {
INSTANCE = new QZAdbRemote();
@@ -96,6 +93,7 @@ public class QZAdbRemote implements DeviceConnectionListener {
@Override
public void receivedData(DeviceConnection devConn, byte[] data, int offset, int length) {
Log.i(LOG_TAG, data.toString());
}
@Override
@@ -105,8 +103,7 @@ public class QZAdbRemote implements DeviceConnectionListener {
@Override
public void consoleUpdated(DeviceConnection devConn, ConsoleBuffer console) {
receiveBuffer += new String(console.buffer);
Log.i(LOG_TAG, new String(console.buffer));
}
@@ -198,12 +195,6 @@ public class QZAdbRemote implements DeviceConnectionListener {
}
}
static public String getReceiveData() {
receiveOldBuffer = receiveBuffer;
receiveBuffer = "";
return receiveOldBuffer;
}
static public void sendCommand(String command) {
Log.d(LOG_TAG, "sendCommand " + ADBConnected + " " + command);
if(ADBConnected) {

View File

@@ -1,308 +0,0 @@
/*
* Copyright 2012 Dynastream Innovations Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.cagnulen.qdomyoszwift;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import com.dsi.ant.channel.AntChannel;
import com.dsi.ant.channel.AntCommandFailedException;
import com.dsi.ant.channel.IAntChannelEventHandler;
import com.dsi.ant.message.ChannelId;
import com.dsi.ant.message.ChannelType;
import com.dsi.ant.message.EventCode;
import com.dsi.ant.message.fromant.ChannelEventMessage;
import com.dsi.ant.message.fromant.MessageFromAntType;
import com.dsi.ant.message.ipc.AntMessageParcel;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import java.util.Random;
public class SDMChannelController {
// The device type and transmission type to be part of the channel ID message
private static final int CHANNEL_SPEED_DEVICE_TYPE = 0x7C;
private static final int CHANNEL_SPEED_TRANSMISSION_TYPE = 1;
// The period and frequency values the channel will be configured to
private static final int CHANNEL_SPEED_PERIOD = 8134; // 1 Hz
private static final int CHANNEL_SPEED_FREQUENCY = 57;
private static final String TAG = SDMChannelController.class.getSimpleName();
public static final int SPEED_SENSOR_ID = 0x9e3d4b99;
private static final double MILLISECOND_TO_1_1024_CONVERSION = 0.9765625;
private AntChannel mAntChannel;
private ChannelEventCallback mChannelEventCallback = new ChannelEventCallback();
private boolean mIsOpen;
double speed = 0.0;
int cadence = 0;
byte stride_count = 0;
public SDMChannelController(AntChannel antChannel) {
mAntChannel = antChannel;
openChannel();
}
boolean openChannel() {
if (null != mAntChannel) {
if (mIsOpen) {
Log.w(TAG, "Channel was already open");
} else {
// Channel ID message contains device number, type and transmission type. In
// order for master (TX) channels and slave (RX) channels to connect, they
// must have the same channel ID, or wildcard (0) is used.
ChannelId channelId = new ChannelId(SPEED_SENSOR_ID & 0xFFFF,
CHANNEL_SPEED_DEVICE_TYPE, CHANNEL_SPEED_TRANSMISSION_TYPE);
try {
// Setting the channel event handler so that we can receive messages from ANT
mAntChannel.setChannelEventHandler(mChannelEventCallback);
// Performs channel assignment by assigning the type to the channel. Additional
// features (such as, background scanning and frequency agility) can be enabled
// by passing an ExtendedAssignment object to assign(ChannelType, ExtendedAssignment).
mAntChannel.assign(ChannelType.BIDIRECTIONAL_MASTER);
/*
* Configures the channel ID, messaging period and rf frequency after assigning,
* then opening the channel.
*
* For any additional ANT features such as proximity search or background scanning, refer to
* the ANT Protocol Doc found at:
* http://www.thisisant.com/resources/ant-message-protocol-and-usage/
*/
mAntChannel.setChannelId(channelId);
mAntChannel.setPeriod(CHANNEL_SPEED_PERIOD);
mAntChannel.setRfFrequency(CHANNEL_SPEED_FREQUENCY);
mAntChannel.open();
mIsOpen = true;
Log.d(TAG, "Opened channel with device number: " + SPEED_SENSOR_ID);
} catch (RemoteException e) {
channelError(e);
} catch (AntCommandFailedException e) {
// This will release, and therefore unassign if required
channelError("Open failed", e);
}
}
} else {
Log.w(TAG, "No channel available");
}
return mIsOpen;
}
void channelError(RemoteException e) {
String logString = "Remote service communication failed.";
Log.e(TAG, logString);
}
void channelError(String error, AntCommandFailedException e) {
StringBuilder logString;
if (e.getResponseMessage() != null) {
String initiatingMessageId = "0x" + Integer.toHexString(
e.getResponseMessage().getInitiatingMessageId());
String rawResponseCode = "0x" + Integer.toHexString(
e.getResponseMessage().getRawResponseCode());
logString = new StringBuilder(error)
.append(". Command ")
.append(initiatingMessageId)
.append(" failed with code ")
.append(rawResponseCode);
} else {
String attemptedMessageId = "0x" + Integer.toHexString(
e.getAttemptedMessageType().getMessageId());
String failureReason = e.getFailureReason().toString();
logString = new StringBuilder(error)
.append(". Command ")
.append(attemptedMessageId)
.append(" failed with reason ")
.append(failureReason);
}
Log.e(TAG, logString.toString());
mAntChannel.release();
Log.e(TAG, "ANT Command Failed");
}
public void close() {
// TODO kill all our resources
if (null != mAntChannel) {
mIsOpen = false;
// Releasing the channel to make it available for others.
// After releasing, the AntChannel instance cannot be reused.
mAntChannel.release();
mAntChannel = null;
}
Log.e(TAG, "Channel Closed");
}
/**
* Implements the Channel Event Handler Interface so that messages can be
* received and channel death events can be handled.
*/
public class ChannelEventCallback implements IAntChannelEventHandler {
long lastTime = 0;
double totalWay = 0.0;
double totalRotations = 0.0;
long lastSpeedEventTime = 0;
long lastCadenceEventTime = 0;
long elapsedMillis = 0;
int rotations;
int rev;
double wheel = 0.1;
Timer carousalTimer = null;
@Override
public void onChannelDeath() {
// Display channel death message when channel dies
Log.e(TAG, "Channel Death");
}
@Override
public void onReceiveMessage(MessageFromAntType messageType, AntMessageParcel antParcel) {
Log.d(TAG, "Rx: " + antParcel);
Log.d(TAG, "Message Type: " + messageType);
if(carousalTimer == null) {
carousalTimer = new Timer(); // At this line a new Thread will be created
carousalTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Log.d(TAG, "Tx Unsollicited");
long realtimeMillis = SystemClock.elapsedRealtime();
double speedM_s = speed / 3.6;
long deltaTime = (realtimeMillis - lastTime);
lastTime = realtimeMillis;
byte[] payload = new byte[8];
payload[0] = (byte) 0x01;
payload[1] = (byte) (((lastTime % 256000) / 5) & 0xFF);
payload[2] = (byte) ((lastTime % 256000) / 1000);
payload[3] = (byte) 0x00;
payload[4] = (byte) speedM_s;
payload[5] = (byte) ((speedM_s - (double)((int)speedM_s)) / (1.0/256.0));
payload[6] = (byte) stride_count++; // bad but it works on zwift
payload[7] = (byte) ((double)deltaTime * 0.03125);
if (mIsOpen) {
try {
// Setting the data to be broadcast on the next channel period
mAntChannel.setBroadcastData(payload);
} catch (RemoteException e) {
channelError(e);
}
}
}
}, 0, 250); // delay
}
// Switching on message type to handle different types of messages
switch (messageType) {
// If data message, construct from parcel and update channel data
case BROADCAST_DATA:
// Rx Data
//updateData(new BroadcastDataMessage(antParcel).getPayload());
break;
case ACKNOWLEDGED_DATA:
// Rx Data
//updateData(new AcknowledgedDataMessage(antParcel).getPayload());
break;
case CHANNEL_EVENT:
// Constructing channel event message from parcel
ChannelEventMessage eventMessage = new ChannelEventMessage(antParcel);
EventCode code = eventMessage.getEventCode();
Log.d(TAG, "Event Code: " + code);
// Switching on event code to handle the different types of channel events
switch (code) {
case TX:
long realtimeMillis = SystemClock.elapsedRealtime();
double speedM_s = speed / 3.6;
long deltaTime = (realtimeMillis - lastTime);
// in case the treadmill doesn't provide cadence, I have to force it. ANT+ requires cadence
lastTime = realtimeMillis;
byte[] payload = new byte[8];
payload[0] = (byte) 0x01;
payload[1] = (byte) (((lastTime % 256000) / 5) & 0xFF);
payload[2] = (byte) ((lastTime % 256000) / 1000);
payload[3] = (byte) 0x00;
payload[4] = (byte) speedM_s;
payload[5] = (byte) ((speedM_s - (double)((int)speedM_s)) / (1.0/256.0));
payload[6] = (byte) stride_count;
payload[7] = (byte) ((double)deltaTime * 0.03125);
if (mIsOpen) {
try {
// Setting the data to be broadcast on the next channel period
mAntChannel.setBroadcastData(payload);
} catch (RemoteException e) {
channelError(e);
}
}
break;
case CHANNEL_COLLISION:
break;
case RX_SEARCH_TIMEOUT:
// TODO May want to keep searching
Log.e(TAG, "No Device Found");
break;
case CHANNEL_CLOSED:
case RX_FAIL:
case RX_FAIL_GO_TO_SEARCH:
case TRANSFER_RX_FAILED:
case TRANSFER_TX_COMPLETED:
case TRANSFER_TX_FAILED:
case TRANSFER_TX_START:
case UNKNOWN:
// TODO More complex communication will need to handle these events
break;
}
break;
case ANT_VERSION:
case BURST_TRANSFER_DATA:
case CAPABILITIES:
case CHANNEL_ID:
case CHANNEL_RESPONSE:
case CHANNEL_STATUS:
case SERIAL_NUMBER:
case OTHER:
// TODO More complex communication will need to handle these message types
break;
}
}
}
}

View File

@@ -8,6 +8,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
@@ -44,6 +45,16 @@ import android.graphics.Point;
import androidx.core.util.Pair;
import com.baidu.paddle.fastdeploy.LitePowerMode;
import com.equationl.fastdeployocr.OCR;
import com.equationl.fastdeployocr.OcrConfig;
import com.equationl.fastdeployocr.RunPrecision;
import com.equationl.fastdeployocr.RunType;
import com.equationl.fastdeployocr.bean.OcrResult;
import com.equationl.fastdeployocr.bean.OcrResultModel;
import com.equationl.fastdeployocr.callback.OcrInitCallback;
import com.equationl.fastdeployocr.callback.OcrRunCallback;
public class ScreenCaptureService extends Service {
private static final String TAG = "ScreenCaptureService";
@@ -76,6 +87,9 @@ public class ScreenCaptureService extends Service {
private static String lastTextExtended = "";
private static boolean isRunning = false;
private OcrConfig config = new OcrConfig();
private OCR ocr = null;
public static String getLastText() {
return lastText;
}
@@ -141,72 +155,45 @@ public class ScreenCaptureService extends Service {
mHeightImage = mHeight;
final Bitmap bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
/*
// write bitmap to a file
fos = new FileOutputStream(mStoreDir + "/myscreen.png");
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos = new FileOutputStream(mStoreDir + "/myscreen.jpg");
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
IMAGES_PRODUCED++;
Log.e(TAG, "captured image: " + IMAGES_PRODUCED);
*/
InputImage inputImage = InputImage.fromBitmap(bitmap, 0);
/*InputImage inputImage = InputImage.fromByteBuffer(buffer,
mWidth + rowPadding / pixelStride, mHeight,
0,
InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12
);*/
Bitmap bMap = BitmapFactory.decodeFile(mStoreDir + "/processed_screenshot.jpg");
Task<Text> result =
recognizer.process(inputImage)
.addOnSuccessListener(new OnSuccessListener<Text>() {
@Override
public void onSuccess(Text result) {
// Task completed successfully
//Log.e(TAG, "Image done!");
String resultText = result.getText();
lastText = resultText;
lastTextExtended = "";
for (Text.TextBlock block : result.getTextBlocks()) {
String blockText = block.getText();
Point[] blockCornerPoints = block.getCornerPoints();
Rect blockFrame = block.getBoundingBox();
lastTextExtended = lastTextExtended + blockText + "$$" + blockFrame.toString() + "§§";
/*for (Text.Line line : block.getLines()) {
String lineText = line.getText();
Point[] lineCornerPoints = line.getCornerPoints();
Rect lineFrame = line.getBoundingBox();
for (Text.Element element : line.getElements()) {
String elementText = element.getText();
Point[] elementCornerPoints = element.getCornerPoints();
Rect elementFrame = element.getBoundingBox();
for (Text.Symbol symbol : element.getSymbols()) {
String symbolText = symbol.getText();
Point[] symbolCornerPoints = symbol.getCornerPoints();
Rect symbolFrame = symbol.getBoundingBox();
}
}
}*/
}
bitmap.recycle();
isRunning = false;
}
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// Task failed with an exception
//Log.e(TAG, "Image fail");
isRunning = false;
}
});
} else {
//Log.e(TAG, "Image ignored");
}
ocr.run(bMap, new OcrRunCallback() {
@Override
public void onSuccess(OcrResult result) {
lastText = result.getSimpleText();
lastTextExtended = "";
/*
for (int index = 0; index < result.getOutputRawResult().size(); index++) {
OcrResultModel ocrResultModel = result.getOutputRawResult().get(index);
// 文字方向 ocrResultModel.clsLabel 可能为 "0" 或 "180"
lastText += ocrResultModel.getClsLabel();
lastTextExtended += index + ": 文字方向:" + ocrResultModel.getClsLabel() +
";文字方向置信度:" + ocrResultModel.getClsConfidenceL() +
";识别置信度 " + ocrResultModel.getConfidence() +
";;文字位置:" + ocrResultModel.getPoints() + "\n";
}*/
isRunning = false;
bitmap.recycle();
Log.e(TAG, "onSuccess: " + lastText);
}
@Override
public void onFail(Throwable e) {
Log.e(TAG, "onFail: 识别失败!", e);
isRunning = false;
bitmap.recycle();
}
});
}
}
} catch (Exception e) {
e.printStackTrace();
}
@@ -263,6 +250,71 @@ public class ScreenCaptureService extends Service {
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate1");
config.setModelPath("models/ch_PP-OCRv2"); // 不使用 "/" 开头的路径表示安装包中 assets 目录下的文件,例如当前表示 assets/models/ocr_v2_for_cpu
//config.modelPath = "/sdcard/Android/data/com.equationl.paddleocr4android.app/files/models" // 使用 "/" 表示手机储存路径,测试时请将下载的三个模型放置于该目录下
/*
config.setClsModelFilename("cls.nb"); // cls 模型文件名
config.setDetModelFilename("det_db.nb"); // det 模型文件名
config.setRecModelFilename("rec_crnn.nb"); // rec 模型文件名
*/
/* already true by default
config.setIsRunDet(true);
config.setIsRunCls(true);
config.setIsRunRec(true);*/
// 运行全部模型
config.setRunType(RunType.All);
// 使用所有核心运行
config.setCpuPowerMode(LitePowerMode.LITE_POWER_FULL);
// 绘制文本位置
//config.setIsDrwwTextPositionBox(true);
// 如果是原始模型,则使用 FP16 精度
config.setRecRunPrecision(RunPrecision.LiteFp16);
config.setDetRunPrecision(RunPrecision.LiteFp16);
config.setClsRunPrecision(RunPrecision.LiteFp16);
Log.i(TAG, "onCreate2");
// 如果是量化模型则使用 int8 精度
//config.recRunPrecision(RunPrecision.LiteInt8
//config.detRunPrecision(RunPrecision.LiteInt8
//config.clsRunPrecision(RunPrecision.LiteInt8
// 1.同步初始化
/*ocr.initModelSync(config).fold(
{
if (it) {
Log.i(TAG, "onCreate: init success")
}
},
{
it.printStackTrace()
}
)*/
// 2.异步初始化
ocr = new OCR(this);
ocr.initModel(config, new OcrInitCallback() {
@Override
public void onSuccess() {
Log.i(TAG, "onSuccess: 初始化成功");
}
@Override
public void onFail(Throwable e) {
Log.e(TAG, "onFail: 初始化失败", e);
}
});
Log.i(TAG, "onCreate3");
// create store dir
File externalFilesDir = getExternalFilesDir(null);
if (externalFilesDir != null) {

View File

@@ -1,42 +0,0 @@
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 androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
public class WearableController {
static Context _context;
static Intent _intent = null;
public static void start(Context context) {
_context = context;
if(_intent == null)
_intent = new Intent(context, WearableMessageListenerService.class);
// FloatingWindowGFG service is started
context.startService(_intent);
Log.v("WearableController", "started");
}
public static int getHeart() {
return WearableMessageListenerService.getHeart();
}
}

View File

@@ -1,131 +0,0 @@
package org.cagnulen.qdomyoszwift;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.MessageClient;
import com.google.android.gms.wearable.DataClient;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.wearable.DataItemBuffer;
import com.google.android.gms.wearable.DataMap;
import android.util.Log;
import android.os.Bundle;
import com.google.android.gms.common.api.Status;
import java.io.InputStream;
public class WearableMessageListenerService extends Service implements
MessageClient.OnMessageReceivedListener, GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,DataClient.OnDataChangedListener {
private GoogleApiClient googleApiClient;
private MessageClient mWearableClient;
private String TAG = "WearableMessageListenerService";
private static int heart_rate = 0;
@Override
public void onCreate() {
super.onCreate();
Log.v("WearableMessageListenerService","onCreate");
}
public static int getHeart() {
return heart_rate;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Your service logic here
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks (this)
.addOnConnectionFailedListener(this)
.build();
googleApiClient.connect();
// Register the MessageClient.OnMessageReceivedListener
mWearableClient = Wearable.getMessageClient(this);
mWearableClient.addListener(this);
Wearable.getDataClient(this).addListener(this);
Log.v("WearableMessageListenerService","onStartCommand");
// Return START_STICKY to restart the service if it's killed by the system
return START_STICKY;
}
@Override
public void onDataChanged(DataEventBuffer dataEvents) {
for (DataEvent event : dataEvents) {
if (event.getType() == DataEvent.TYPE_DELETED) {
Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
} else if (event.getType() == DataEvent.TYPE_CHANGED) {
Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri() + " " + event.getDataItem().getUri().getPath());
if(event.getDataItem().getUri().getPath().equals("/qz")) {
new Thread(new Runnable() {
@Override
public void run() {
DataItemBuffer result = Wearable.DataApi.getDataItems(googleApiClient).await();
if (result.getStatus().isSuccess()) {
if (result.getCount() == 1) {
heart_rate = DataMap.fromByteArray(result.get(0).getData())
.getInt("heart_rate", 0);
} else {
Log.e(TAG, "Unexpected number of DataItems found.\n"
+ "\tExpected: 1\n"
+ "\tActual: " + result.getCount());
}
} else if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onHandleIntent: failed to get current alarm state");
}
Log.d(TAG, "Heart: " + heart_rate);
}
}).start();
}
}
}
}
@Override
public void onConnected(Bundle bundle) {
Log.v("WearableMessageListenerService","onConnected");
}
@Override
public void onConnectionSuspended(int i) {
Log.v("WearableMessageListenerService","onConnectionSuspended");
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.v("WearableMessageListenerService","onConnectionFailed");
}
@Override
public void onMessageReceived(final MessageEvent messageEvent) {
String path = messageEvent.getPath();
byte[] data = messageEvent.getData();
// Handle the received message data here
String messageData = new String(data); // Assuming it's a simple string message
Log.v("Wearable", path);
Log.v("Wearable", messageData);
// You can then perform actions or update data in your service based on the received message
}
@Override
public IBinder onBind(Intent intent) {
// This service does not support binding
return null;
}
}

View File

@@ -3,7 +3,7 @@ package com.cgutman.androidremotedebugger.console;
import android.widget.TextView;
public class ConsoleBuffer {
public char[] buffer;
private char[] buffer;
private int amountPopulated;
public ConsoleBuffer(int bufferSize)

View File

@@ -129,7 +129,6 @@ 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;
@@ -160,7 +159,7 @@ void apexbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
if (watts())
KCal +=
@@ -168,17 +167,17 @@ void apexbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
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
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg
//* 3.5) / 200 ) / 60
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
if (Cadence.value() > 0) {
CrankRevs++;
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
#ifdef Q_OS_ANDROID
if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) {

View File

@@ -142,7 +142,6 @@ 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];
@@ -192,7 +191,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic &
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0),
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0),
0 /* not useful for elliptical*/);
}
index += 2;
@@ -242,7 +241,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic &
index += 3;
} else {
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
}
emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value()));
@@ -289,7 +288,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic &
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
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in
// kg * 3.5) / 200 ) / 60
}
@@ -302,7 +301,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic &
#endif
{
if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) {
Heart = ((double)(((uint8_t)newValue.at(index))));
Heart = ((double)((newValue.at(index))));
// index += 1; // NOTE: clang-analyzer-deadcode.DeadStores
emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value()));
} else {
@@ -327,7 +326,7 @@ void bhfitnesselliptical::characteristicChanged(const QLowEnergyCharacteristic &
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
if (heartRateBeltName.startsWith(QStringLiteral("Disabled")) &&
(!Flags.heartRate || Heart.value() == 0 || disable_hr_frommachinery)) {

View File

@@ -116,7 +116,6 @@ void bike::clearStats() {
Speed.clear(false);
KCal.clear(true);
Distance.clear(true);
Distance1s.clear(true);
Heart.clear(false);
m_jouls.clear(true);
elevationAcc = 0;
@@ -141,7 +140,6 @@ 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);
@@ -163,7 +161,6 @@ 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);
@@ -291,8 +288,6 @@ uint16_t bike::wattFromHR(bool useSpeedAndCadence) {
} else {
watt = 0;
}
} else {
watt = currentCadence().value() * 1.2; // random value cloned from Zwift when HR is not available
}
return watt;
}

View File

@@ -12,7 +12,7 @@ class bike : public bluetoothdevice {
public:
bike();
virtualbike *VirtualBike();
virtualbike * VirtualBike();
metric lastRequestedResistance();
metric lastRequestedPelotonResistance();
@@ -36,8 +36,8 @@ class bike : public bluetoothdevice {
uint8_t metrics_override_heartrate() override;
void setGears(double d);
double gears();
void setSpeedLimit(double speed) { m_speedLimit = speed; }
double speedLimit() { return m_speedLimit; }
void setSpeedLimit(double speed) {m_speedLimit = speed;}
double speedLimit() {return m_speedLimit;}
/**
* @brief currentSteeringAngle Gets a metric object to get or set the current steering angle
@@ -46,7 +46,6 @@ class bike : public bluetoothdevice {
*/
metric currentSteeringAngle() { return m_steeringAngle; }
virtual bool inclinationAvailableByHardware();
bool ergModeSupportedAvailableByHardware() { return ergModeSupported; }
public Q_SLOTS:
void changeResistance(resistance_t res) override;

View File

@@ -192,7 +192,6 @@ 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;
@@ -254,8 +253,8 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri
if (cadence >= 0 && cadence < 255) {
Cadence = cadence;
}
lastGoodCadence = now;
} else if (lastGoodCadence.msecsTo(now) > 2000) {
lastGoodCadence = QDateTime::currentDateTime();
} else if (lastGoodCadence.msecsTo(QDateTime::currentDateTime()) > 2000) {
Cadence = 0;
}
@@ -267,7 +266,7 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri
.toDouble();
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
// Resistance = ((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) |
// (uint16_t)((uint8_t)newValue.at(index)))); debug("Current Resistance: " +
@@ -302,9 +301,9 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri
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
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in
// kg * 3.5) / 200 ) / 60
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
emit debug(QStringLiteral("Current CrankRevsRead: ") + QString::number(CrankRevsRead));
emit debug(QStringLiteral("Last CrankEventTime: ") + QString::number(LastCrankEventTime));
@@ -385,8 +384,8 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri
if (cadence >= 0) {
Cadence = cadence;
}
lastGoodCadence = now;
} else if (lastGoodCadence.msecsTo(now) > 2000) {
lastGoodCadence = QDateTime::currentDateTime();
} else if (lastGoodCadence.msecsTo(QDateTime::currentDateTime()) > 2000) {
Cadence = 0;
}
}
@@ -404,12 +403,12 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value()));
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
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
@@ -457,7 +456,7 @@ void bkoolbike::characteristicChanged(const QLowEnergyCharacteristic &characteri
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
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight
// in kg * 3.5) / 200 ) / 60
emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value()));
}

View File

@@ -49,6 +49,25 @@ bluetooth::bluetooth(bool logs, const QString &deviceName, bool noWriteResistanc
this->signalBluetoothDeviceConnected(pelotonBike);
}
// TO REMOVE
bool fakedevice_treadmill =
settings.value(QZSettings::fakedevice_treadmill, QZSettings::default_fakedevice_treadmill).toBool();
if(fakedevice_treadmill) {
fakeTreadmill = new faketreadmill(noWriteResistance, noHeartService, false);
emit deviceConnected(QBluetoothDeviceInfo());
connect(fakeTreadmill, &bluetoothdevice::connectedAndDiscovered, this,
&bluetooth::connectedAndDiscovered);
connect(fakeTreadmill, &faketreadmill::inclinationChanged, this, &bluetooth::inclinationChanged);
// connect(cscBike, SIGNAL(disconnected()), this, SLOT(restart()));
// connect(this, SIGNAL(searchingStop()), fakeBike, SLOT(searchingStop())); //NOTE: Commented due to
// #358
if (this->discoveryAgent && !this->discoveryAgent->isActive()) {
emit searchingStop();
}
this->signalBluetoothDeviceConnected(fakeTreadmill);
return;
}
#ifdef TEST
schwinnIC4Bike = (schwinnic4bike *)new bike();
// this signal is not associated to anything in this moment, since the homeform is not loaded yet
@@ -109,9 +128,8 @@ void bluetooth::finished() {
QSettings settings;
QString nordictrack_2950_ip =
settings.value(QZSettings::nordictrack_2950_ip, QZSettings::default_nordictrack_2950_ip).toString();
QString tdf_10_ip = settings.value(QZSettings::tdf_10_ip, QZSettings::default_tdf_10_ip).toString();
// wifi devices on windows
if (!nordictrack_2950_ip.isEmpty() || !tdf_10_ip.isEmpty()) {
if (!nordictrack_2950_ip.isEmpty()) {
// faking a bluetooth device
qDebug() << "faking a bluetooth device for nordictrack_2950_ip";
deviceDiscovered(QBluetoothDeviceInfo());
@@ -399,7 +417,6 @@ 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 =
@@ -424,10 +441,6 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
bool sole_inclination =
settings.value(QZSettings::sole_treadmill_inclination, QZSettings::default_sole_treadmill_inclination).toBool();
QString ftms_rower = settings.value(QZSettings::ftms_rower, QZSettings::default_ftms_rower).toString();
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) {
@@ -657,21 +670,6 @@ 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();
@@ -732,8 +730,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
this->signalBluetoothDeviceConnected(nordictrackifitadbTreadmill);
} else if (!tdf_10_ip.isEmpty() && !nordictrackifitadbBike) {
this->stopDiscovery();
nordictrackifitadbBike = new nordictrackifitadbbike(noWriteResistance, noHeartService,
bikeResistanceOffset, bikeResistanceGain);
nordictrackifitadbBike = new nordictrackifitadbbike(noWriteResistance, noHeartService);
emit deviceConnected(b);
connect(nordictrackifitadbBike, &bluetoothdevice::connectedAndDiscovered, this,
&bluetooth::connectedAndDiscovered);
@@ -841,8 +838,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
emit searchingStop();
}
this->signalBluetoothDeviceConnected(domyosElliptical);
} else if ((b.name().toUpper().startsWith(QStringLiteral("YPOO-U3-")) ||
(b.name().startsWith(QStringLiteral("FS-")) && iconsole_elliptical)) && !ypooElliptical && filter) {
} else if (b.name().toUpper().startsWith(QStringLiteral("YPOO-U3-")) && !ypooElliptical && filter) {
this->setLastBluetoothDevice(b);
this->stopDiscovery();
ypooElliptical =
@@ -858,8 +854,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
emit searchingStop();
}
this->signalBluetoothDeviceConnected(ypooElliptical);
} else if ((b.name().toUpper().startsWith(QStringLiteral("NAUTILUS E")) ||
b.name().toUpper().startsWith(QStringLiteral("NAUTILUS M"))) &&
} else if ((b.name().toUpper().startsWith(QStringLiteral("NAUTILUS E"))) &&
!nautilusElliptical && // NAUTILUS E616
filter) {
this->setLastBluetoothDevice(b);
@@ -1022,9 +1017,7 @@ 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")) ||
// KingSmith Walking Pad G1
b.name().toUpper().startsWith(QStringLiteral("KS-NGCH-G1C"))) &&
b.name().toUpper().startsWith(QStringLiteral("KS-NGCH-X21C"))) &&
!kingsmithR2Treadmill && filter) {
this->setLastBluetoothDevice(b);
this->stopDiscovery();
@@ -1051,7 +1044,6 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
b.name().toUpper().startsWith(QStringLiteral("WALKINGPAD")) ||
!b.name().toUpper().compare(QStringLiteral("RE")) || // just "RE"
b.name().toUpper().startsWith(QStringLiteral("KS-H")) ||
b.name().toUpper().startsWith(QStringLiteral("KS-BLC")) || // Walkingpad C2 #1672
b.name().toUpper().startsWith(
QStringLiteral("KS-BLR"))) && // Treadmill KingSmith WalkingPad R2 Pro KS-HCR1AA
!kingsmithR1ProTreadmill &&
@@ -1116,7 +1108,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
if (this->discoveryAgent && !this->discoveryAgent->isActive())
emit searchingStop();
this->signalBluetoothDeviceConnected(trueTreadmill);
} else if (((b.name().toUpper().startsWith(QStringLiteral("F80")) && sole_inclination) ||
} else if ((b.name().toUpper().startsWith(QStringLiteral("F80")) ||
b.name().toUpper().startsWith(QStringLiteral("F65")) ||
b.name().toUpper().startsWith(QStringLiteral("TT8")) ||
b.name().toUpper().startsWith(QStringLiteral("F63")) ||
@@ -1187,20 +1179,16 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
b.name().toUpper().startsWith(QStringLiteral("CT800")) || // FTMS
b.name().toUpper().startsWith(QStringLiteral("TRX4500")) || // FTMS
b.name().toUpper().startsWith(QStringLiteral("MATRIXTF50")) || // FTMS
b.name().toUpper().startsWith(QStringLiteral("T01_")) || // FTMS
(b.name().toUpper().startsWith(QStringLiteral("TF-")) &&
horizon_treadmill_force_ftms) || // FTMS, TF-769DF2
((b.name().toUpper().startsWith(QStringLiteral("TOORX")) ||
(b.name().toUpper().startsWith(QStringLiteral("I-CONSOLE+")))) &&
!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("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);
@@ -1229,11 +1217,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
} else if ((b.name().toUpper().startsWith(QStringLiteral("MYRUN ")) ||
b.name().toUpper().startsWith(QStringLiteral("MERACH-U3")) // FTMS
) &&
!technogymmyrunTreadmill
#ifndef Q_OS_IOS
&& !technogymmyrunrfcommTreadmill
#endif
&& filter) {
!technogymmyrunTreadmill && filter) {
this->setLastBluetoothDevice(b);
this->stopDiscovery();
bool technogym_myrun_treadmill_experimental =
@@ -1293,9 +1277,9 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
this->signalBluetoothDeviceConnected(technogymmyrunrfcommTreadmill);
}
#endif
} else if ((b.name().toUpper().startsWith("TACX ") ||
} else if ((b.name().toUpper().startsWith("TACX NEO") ||
b.name().toUpper().startsWith(QStringLiteral("TACX FLOW")) ||
b.name().toUpper().startsWith(QStringLiteral("THINK X")) ||
b.address() == QBluetoothAddress("C1:14:D9:9C:FB:01") || // specific TACX NEO 2 #1707
(b.name().toUpper().startsWith("TACX SMART BIKE"))) &&
!tacxneo2Bike && filter) {
this->setLastBluetoothDevice(b);
@@ -1331,33 +1315,28 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
npeCableBike->deviceDiscovered(b);
this->signalBluetoothDeviceConnected(npeCableBike);
} else if (((b.name().startsWith("FS-") && hammerRacerS) ||
(b.name().toUpper().startsWith("DI") && b.name().length() == 2) || // Elite smart trainer #1682
(b.name().toUpper().startsWith("DHZ-")) || // JK fitness 577
(b.name().toUpper().startsWith("MKSM")) || // MKSM3600036
(b.name().toUpper().startsWith("YS_C1_")) || // Yesoul C1H
(b.name().toUpper().startsWith("YS_G1_")) || // Yesoul S3
(b.name().toUpper().startsWith("DS25-")) || // Bodytone DS25
(b.name().toUpper().startsWith("DHZ-")) || // JK fitness 577
(b.name().toUpper().startsWith("MKSM")) || // MKSM3600036
(b.name().toUpper().startsWith("YS_C1_")) || // Yesoul C1H
(b.name().toUpper().startsWith("YS_G1_")) || // Yesoul S3
(b.name().toUpper().startsWith("DS25-")) || // Bodytone DS25
(b.name().toUpper().startsWith("SCHWINN 510T")) ||
(b.name().toUpper().startsWith("ZWIFT HUB")) || (b.name().toUpper().startsWith("MAGNUS ")) ||
(b.name().toUpper().startsWith("HAMMER ") && !power_as_bike && !saris_trainer) || // HAMMER 64123
(b.name().toUpper().startsWith("HAMMER ")) || // HAMMER 64123
(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
(b.name().toUpper().startsWith("DBF") && b.name().length() == 6) || // DBF135
(b.name().toUpper().startsWith(ftmsAccessoryName.toUpper()) &&
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("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("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"))) &&
(b.name().toUpper().startsWith("DIRETO XR")) || (b.name().toUpper().startsWith("SMB1")) ||
(b.name().toUpper().startsWith("INRIDE"))) &&
!ftmsBike && !snodeBike && !fitPlusBike && !stagesBike && filter) {
this->setLastBluetoothDevice(b);
this->stopDiscovery();
@@ -1370,7 +1349,6 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
this->signalBluetoothDeviceConnected(ftmsBike);
} else if ((b.name().toUpper().startsWith("KICKR SNAP") || b.name().toUpper().startsWith("KICKR BIKE") ||
b.name().toUpper().startsWith("KICKR ROLLR") ||
(b.name().toUpper().startsWith("HAMMER ") && saris_trainer) ||
(b.name().toUpper().startsWith("WAHOO KICKR"))) &&
!wahooKickrSnapBike && filter) {
this->setLastBluetoothDevice(b);
@@ -1399,7 +1377,6 @@ 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) {
@@ -1453,7 +1430,6 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
b.name().toUpper().startsWith(QStringLiteral("KS-WLT")) || // KS-WLT-W1
b.name().toUpper().startsWith(QStringLiteral("I-ROWER")) ||
b.name().toUpper().startsWith(QStringLiteral("SF-RW")) ||
b.name().toUpper().startsWith(QStringLiteral("DFIT-L-R")) ||
!b.name().compare(ftms_rower, Qt::CaseInsensitive) ||
(b.name().toUpper().startsWith(QStringLiteral("PM5")) &&
b.name().toUpper().endsWith(QStringLiteral("ROW")))) &&
@@ -1472,7 +1448,6 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
this->signalBluetoothDeviceConnected(ftmsRower);
} else if ((b.name().toUpper().startsWith(QLatin1String("ECH-STRIDE")) ||
b.name().toUpper().startsWith(QLatin1String("ECH-UK-")) ||
b.name().toUpper().startsWith(QLatin1String("ECH-FR-")) ||
b.name().toUpper().startsWith(QLatin1String("ECH-SD-SPT"))) &&
!echelonStride && filter) {
this->setLastBluetoothDevice(b);
@@ -1806,8 +1781,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
// SLOT(inclinationChanged(double)));
mcfBike->deviceDiscovered(b);
this->signalBluetoothDeviceConnected(mcfBike);
} else if ((b.name().startsWith(QStringLiteral("TRX ROUTE KEY")) ||
b.name().toUpper().startsWith(QStringLiteral("BH-TR-"))) && !toorx && filter) {
} else if ((b.name().startsWith(QStringLiteral("TRX ROUTE KEY"))) && !toorx && filter) {
this->setLastBluetoothDevice(b);
this->stopDiscovery();
toorx = new toorxtreadmill();
@@ -1876,7 +1850,6 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
(b.name().toUpper().startsWith(QStringLiteral("ICONSOLE+"))) ||
(b.name().toUpper().startsWith(QStringLiteral("I-RUNNING"))) ||
(b.name().toUpper().startsWith(QStringLiteral("DKN RUN"))) ||
(b.name().toUpper().startsWith(QStringLiteral("ADIDAS "))) ||
(b.name().toUpper().startsWith(QStringLiteral("REEBOK")))) &&
!trxappgateusb && !trxappgateusbBike && !toorx_bike && !toorx_ftms && !toorx_ftms_treadmill &&
filter) {
@@ -1891,8 +1864,6 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
trxappgateusb->deviceDiscovered(b);
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+")) ||
@@ -1963,7 +1934,6 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
skandikaWiriBike->deviceDiscovered(b);
this->signalBluetoothDeviceConnected(skandikaWiriBike);
} else if (((b.name().toUpper().startsWith("RQ") && b.name().length() == 5) ||
(b.name().toUpper().startsWith("R-Q") && b.name().length() > 6) ||
(b.name().toUpper().startsWith("SCH130")) || // not a renpho bike an FTMS one
((b.name().startsWith(QStringLiteral("TOORX"))) && toorx_ftms && !toorx_ftms_treadmill)) &&
!renphoBike && !snodeBike && !fitPlusBike && filter) {
@@ -2016,13 +1986,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-")) && !horizonTreadmill && !snode_bike && !fitplus_bike && !ftmsBike && !iconsole_elliptical) ||
} else if (((b.name().startsWith(QStringLiteral("FS-")) && !snode_bike && !fitplus_bike && !ftmsBike) ||
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 && !iconsole_elliptical && filter) {
!fitshowTreadmill && filter) {
this->setLastBluetoothDevice(b);
this->stopDiscovery();
fitshowTreadmill = new fitshowtreadmill(this->pollDeviceTime, noConsole, noHeartService);
@@ -2232,16 +2202,6 @@ 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;
}
}
}
@@ -2364,12 +2324,10 @@ void bluetooth::connectedAndDiscovered() {
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative",
"activity", "()Landroid/app/Activity;");
KeepAwakeHelper::antObject(true)->callMethod<void>(
"antStart", "(Landroid/app/Activity;ZZZZ)V", activity.object<jobject>(),
"antStart", "(Landroid/app/Activity;ZZZ)V", activity.object<jobject>(),
settings.value(QZSettings::ant_cadence, QZSettings::default_ant_cadence).toBool(),
settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool(),
settings.value(QZSettings::ant_garmin, QZSettings::default_ant_garmin).toBool(),
device()->deviceType() == bluetoothdevice::TREADMILL ||
device()->deviceType() == bluetoothdevice::ELLIPTICAL);
settings.value(QZSettings::ant_garmin, QZSettings::default_ant_garmin).toBool());
}
if (settings.value(QZSettings::android_notification, QZSettings::default_android_notification).toBool()) {
@@ -2568,11 +2526,6 @@ void bluetooth::restart() {
delete proformWifiBike;
proformWifiBike = nullptr;
}
if (proformTelnetBike) {
delete proformTelnetBike;
proformTelnetBike = nullptr;
}
if (proformWifiTreadmill) {
delete proformWifiTreadmill;
@@ -2919,14 +2872,6 @@ void bluetooth::restart() {
}
wahookickrHeadWind.clear();
}
if (eliteAriaFan.length()) {
foreach (eliteariafan *f, eliteAriaFan) {
delete f;
f = nullptr;
}
eliteAriaFan.clear();
}
if (cadenceSensor) {
// heartRateBelt->disconnectBluetooth(); // to test
@@ -2986,8 +2931,6 @@ bluetoothdevice *bluetooth::device() {
return cscBike;
} else if (proformWifiBike) {
return proformWifiBike;
} else if (proformTelnetBike) {
return proformTelnetBike;
} else if (proformWifiTreadmill) {
return proformWifiTreadmill;
} else if (nordictrackifitadbTreadmill) {
@@ -3257,10 +3200,6 @@ 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;
}

View File

@@ -41,7 +41,6 @@
#include "echelonconnectsport.h"
#include "echelonrower.h"
#include "eliteariafan.h"
#include "eliterizer.h"
#include "elitesterzosmart.h"
#include "eslinkertreadmill.h"
@@ -86,7 +85,6 @@
#include "proformellipticaltrainer.h"
#include "proformrower.h"
#include "proformtreadmill.h"
#include "proformtelnetbike.h"
#include "proformwifibike.h"
#include "proformwifitreadmill.h"
#include "schwinn170bike.h"
@@ -188,7 +186,6 @@ 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;
@@ -253,7 +250,6 @@ class bluetooth : public QObject, public SignalHandler {
faketreadmill *fakeTreadmill = nullptr;
QList<fitmetria_fanfit *> fitmetriaFanfit;
QList<wahookickrheadwind *> wahookickrHeadWind;
QList<eliteariafan *> eliteAriaFan;
QString filterDevice = QLatin1String("");
bool testResistance = false;

View File

@@ -247,15 +247,9 @@ void bluetoothdevice::update_hr_from_external() {
long appleWatchHeartRate = h.heartRate();
h.setKcal(KCal.value());
h.setDistance(Distance.value());
h.setSpeed(Speed.value());
h.setPower(m_watt.value());
h.setCadence(Cadence.value());
Heart = appleWatchHeartRate;
qDebug() << "Current Heart from Apple Watch: " << QString::number(appleWatchHeartRate);
#endif
#endif
#ifdef Q_OS_ANDROID
Heart = QAndroidJniObject::callStaticMethod<jint>("org/cagnulen/qdomyoszwift/WearableController", "getHeart", "()I");
#endif
}
}
@@ -267,7 +261,6 @@ void bluetoothdevice::clearStats() {
Speed.clear(false);
KCal.clear(true);
Distance.clear(true);
Distance1s.clear(true);
Heart.clear(false);
m_jouls.clear(true);
elevationAcc = 0;
@@ -285,7 +278,6 @@ 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);
@@ -301,7 +293,6 @@ 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);

View File

@@ -100,9 +100,6 @@ 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.
@@ -498,7 +495,6 @@ 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

View File

@@ -6,15 +6,18 @@ CharacteristicNotifier2A53::CharacteristicNotifier2A53(bluetoothdevice *Bike, QO
int CharacteristicNotifier2A53::notify(QByteArray &value) {
bluetoothdevice::BLUETOOTH_TYPE dt = Bike->deviceType();
value.append(0x02); // total distance
uint16_t speed = Bike->currentSpeed().value() / 3.6 * 256;
uint32_t distance = Bike->odometer() * 10000.0;
value.append((char)((speed & 0xFF)));
value.append((char)((speed >> 8) & 0xFF));
value.append((char)(Bike->currentCadence().value()));
value.append((char)((distance & 0xFF)));
value.append((char)((distance >> 8) & 0xFF));
value.append((char)((distance >> 16) & 0xFF));
value.append((char)((distance >> 24) & 0xFF));
return CN_OK;
if (dt == bluetoothdevice::TREADMILL || dt == bluetoothdevice::ELLIPTICAL) {
value.append(0x02); // total distance
uint16_t speed = Bike->currentSpeed().value() / 3.6 * 256;
uint32_t distance = Bike->odometer() * 10000.0;
value.append((char)((speed & 0xFF)));
value.append((char)((speed >> 8) & 0xFF));
value.append((char)(Bike->currentCadence().value()));
value.append((char)((distance & 0xFF)));
value.append((char)((distance >> 8) & 0xFF));
value.append((char)((distance >> 16) & 0xFF));
value.append((char)((distance >> 24) & 0xFF));
return CN_OK;
} else
return CN_INVALID;
}

View File

@@ -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)0x0F); // resistance, power, speed and inclination target supported
value.append((char)0x0C); // resistance and power target supported
value.append((char)0xE0); // indoor simulation, wheel and spin down supported
value.append((char)0x00);
value.append((char)0x00);

View File

@@ -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(0x0C); // Inclination available and distance for peloton
value.append(0x08); // Inclination available
value.append((char)0x01); // heart rate available
uint16_t normalizeSpeed = (uint16_t)qRound(Bike->currentSpeed().value() * 100);
@@ -17,17 +17,6 @@ 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);
@@ -47,8 +36,6 @@ int CharacteristicNotifier2ACD::notify(QByteArray &value) {
rampBytes.append(a);
value.append(speedBytes); // Actual value.
value.append(distanceBytes); // Actual value.
value.append(inclineBytes); // incline

View File

@@ -1,6 +1,5 @@
#include "characteristicnotifier2ad2.h"
#include "elliptical.h"
#include "rower.h"
#include "treadmill.h"
#include <QSettings>
@@ -9,17 +8,11 @@ CharacteristicNotifier2AD2::CharacteristicNotifier2AD2(bluetoothdevice *Bike, QO
int CharacteristicNotifier2AD2::notify(QByteArray &value) {
bluetoothdevice::BLUETOOTH_TYPE dt = Bike->deviceType();
QSettings settings;
bool virtual_device_rower =
settings.value(QZSettings::virtual_device_rower, QZSettings::default_virtual_device_rower).toBool();
bool rowerAsABike = !virtual_device_rower && dt == bluetoothdevice::ROWING;
double normalizeWattage = Bike->wattsMetric().value();
if (normalizeWattage < 0)
normalizeWattage = 0;
if (dt == bluetoothdevice::BIKE || rowerAsABike) {
if (dt == bluetoothdevice::BIKE) {
uint16_t normalizeSpeed = (uint16_t)qRound(Bike->currentSpeed().value() * 100);
value.append((char)0x64); // speed, inst. cadence, resistance lvl, instant power
value.append((char)0x02); // heart rate
@@ -39,7 +32,7 @@ int CharacteristicNotifier2AD2::notify(QByteArray &value) {
value.append(char(Bike->currentHeart().value())); // Actual value.
value.append((char)0); // Bkool FTMS protocol HRM offset 1280 fix
return CN_OK;
} else if (dt == bluetoothdevice::TREADMILL || dt == bluetoothdevice::ELLIPTICAL || dt == bluetoothdevice::ROWING) {
} else if (dt == bluetoothdevice::TREADMILL || dt == bluetoothdevice::ELLIPTICAL) {
QSettings settings;
bool double_cadence = settings.value(QZSettings::powr_sensor_running_cadence_double, QZSettings::default_powr_sensor_running_cadence_double).toBool();
double cadence_multiplier = 2.0;
@@ -57,8 +50,6 @@ int CharacteristicNotifier2AD2::notify(QByteArray &value) {
cadence = ((elliptical *)Bike)->currentCadence().value();
else if (dt == bluetoothdevice::TREADMILL)
cadence = ((treadmill *)Bike)->currentCadence().value();
else if (dt == bluetoothdevice::ROWING)
cadence = ((rower *)Bike)->currentCadence().value();
value.append((char)((uint16_t)(cadence * cadence_multiplier) & 0xFF)); // cadence
value.append((char)(((uint16_t)(cadence * cadence_multiplier) >> 8) & 0xFF)); // cadence

View File

@@ -126,7 +126,6 @@ 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;
@@ -154,7 +153,7 @@ void chronobike::characteristicChanged(const QLowEnergyCharacteristic &character
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
if (watts())
KCal +=
@@ -162,10 +161,10 @@ void chronobike::characteristicChanged(const QLowEnergyCharacteristic &character
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
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg
//* 3.5) / 200 ) / 60
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
double ac = 0.01243107769;
double bc = 1.145964912;
@@ -191,7 +190,7 @@ void chronobike::characteristicChanged(const QLowEnergyCharacteristic &character
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
#ifdef Q_OS_ANDROID
if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool())

View File

@@ -131,7 +131,6 @@ 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);
@@ -173,7 +172,7 @@ void concept2skierg::characteristicChanged(const QLowEnergyCharacteristic &chara
break;
case 0x32:
qDebug() << "32";
if (newValue.length() >= 19) {
if (newValue.length() >= 20) {
// 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);
@@ -239,7 +238,7 @@ void concept2skierg::characteristicChanged(const QLowEnergyCharacteristic &chara
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) {
update_hr_from_external();

View File

@@ -182,7 +182,61 @@ int csaferowerThread::openPort() {
tcflush(devicePort, TCIOFLUSH); // clear out the garbage
#else
// WINDOWS USES SET/GETCOMMSTATE AND READ/WRITEFILE
COMMTIMEOUTS timeouts; // timeout settings on serial ports
// if deviceFilename references a port above COM9
// then we need to open "\\.\COMX" not "COMX"
QString portSpec;
int portnum = deviceFilename.midRef(3).toString().toInt();
if (portnum < 10)
portSpec = deviceFilename;
else
portSpec = "\\\\.\\" + deviceFilename;
wchar_t deviceFilenameW[32]; // \\.\COM32 needs 9 characters, 32 should be enough?
MultiByteToWideChar(CP_ACP, 0, portSpec.toLatin1(), -1, (LPWSTR)deviceFilenameW, sizeof(deviceFilenameW));
// win32 commport API
devicePort = CreateFile(deviceFilenameW, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_DELETE | FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (devicePort == INVALID_HANDLE_VALUE)
return -1;
if (GetCommState(devicePort, &deviceSettings) == false)
return -1;
// so we've opened the comm port lets set it up for
deviceSettings.BaudRate = CBR_2400;
deviceSettings.fParity = NOPARITY;
deviceSettings.ByteSize = 8;
deviceSettings.StopBits = ONESTOPBIT;
deviceSettings.XonChar = 11;
deviceSettings.XoffChar = 13;
deviceSettings.EofChar = 0x0;
deviceSettings.ErrorChar = 0x0;
deviceSettings.EvtChar = 0x0;
deviceSettings.fBinary = true;
deviceSettings.fOutX = 0;
deviceSettings.fInX = 0;
deviceSettings.XonLim = 0;
deviceSettings.XoffLim = 0;
deviceSettings.fRtsControl = RTS_CONTROL_ENABLE;
deviceSettings.fDtrControl = DTR_CONTROL_ENABLE;
deviceSettings.fOutxCtsFlow = FALSE; // TRUE;
if (SetCommState(devicePort, &deviceSettings) == false) {
CloseHandle(devicePort);
return -1;
}
timeouts.ReadIntervalTimeout = 0;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 50;
timeouts.WriteTotalTimeoutConstant = 2000;
timeouts.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts(devicePort, &timeouts);
#endif
@@ -337,19 +391,17 @@ void csaferower::update() {
} else
#endif
#endif
{
if (virtual_device_enabled) {
if (!virtual_device_rower) {
qDebug() << QStringLiteral("creating virtual bike interface...");
auto virtualBike = new virtualbike(this, noWriteResistance, noHeartService);
// connect(virtualBike,&virtualbike::debug ,this,&echelonrower::debug);
this->setVirtualDevice(virtualBike, VIRTUAL_DEVICE_MODE::PRIMARY);
} else {
qDebug() << QStringLiteral("creating virtual rower interface...");
auto virtualRower = new virtualrower(this, noWriteResistance, noHeartService);
// connect(virtualRower,&virtualrower::debug ,this,&echelonrower::debug);
this->setVirtualDevice(virtualRower, VIRTUAL_DEVICE_MODE::PRIMARY);
}
if (!virtual_device_rower) {
qDebug() << QStringLiteral("creating virtual bike interface...");
auto virtualBike = new virtualbike(this, noWriteResistance, noHeartService);
// connect(virtualBike,&virtualbike::debug ,this,&echelonrower::debug);
this->setVirtualDevice(virtualBike, VIRTUAL_DEVICE_MODE::PRIMARY);
} else {
qDebug() << QStringLiteral("creating virtual rower interface...");
auto virtualRower = new virtualrower(this, noWriteResistance, noHeartService);
// connect(virtualRower,&virtualrower::debug ,this,&echelonrower::debug);
this->setVirtualDevice(virtualRower, VIRTUAL_DEVICE_MODE::PRIMARY);
}
}
}

View File

@@ -37,9 +37,12 @@
#include <QThread>
#ifdef WIN32
#include <windows.h>
#include <windef.h>
#endif
#ifdef WIN32
#include <winbase.h>
#include <windows.h>
#else
#include <sys/ioctl.h>
#include <termios.h> // unix!!

View File

@@ -89,15 +89,6 @@ void cscbike::update() {
/*initDone*/) {
update_metrics(true, watts());
if(lastGoodCadence.secsTo(QDateTime::currentDateTime()) > 5 && !charNotified) {
readMethod = true;
qDebug() << "no cadence for 5 secs, switching to reading method";
}
if(readMethod && cadenceService) {
cadenceService->readCharacteristic(cadenceChar);
}
// updating the treadmill console every second
if (sec1Update++ == (500 / refresh->interval())) {
sec1Update = 0;
@@ -138,7 +129,6 @@ 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;
@@ -151,8 +141,6 @@ void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characterist
double _WheelRevs = 0;
uint8_t battery = 0;
charNotified = true;
emit debug(QStringLiteral(" << ") + newValue.toHex(' '));
if (characteristic.uuid() == QBluetoothUuid((quint16)0x2A19)) {
@@ -212,8 +200,8 @@ void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characterist
double cadence = ((CrankRevs - oldCrankRevs) / deltaT) * 1024 * 60;
if (cadence >= 0 && cadence < 256)
Cadence = cadence;
lastGoodCadence = now;
} else if (lastGoodCadence.msecsTo(now) > 2000) {
lastGoodCadence = QDateTime::currentDateTime();
} else if (lastGoodCadence.msecsTo(QDateTime::currentDateTime()) > 2000) {
Cadence = 0;
}
emit cadenceChanged(Cadence.value());
@@ -229,12 +217,12 @@ void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characterist
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value()));
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value()));
double ac = 0.01243107769;
@@ -267,7 +255,7 @@ void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characterist
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
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg
//* 3.5) / 200 ) / 60
emit debug(QStringLiteral("Current KCal: ") + QString::number(KCal.value()));
@@ -276,7 +264,7 @@ void cscbike::characteristicChanged(const QLowEnergyCharacteristic &characterist
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
if (!noVirtualDevice) {
#ifdef Q_OS_IOS
@@ -323,16 +311,8 @@ void cscbike::stateChanged(QLowEnergyService::ServiceState state) {
qDebug() << QStringLiteral("all services discovered!");
QBluetoothUuid CyclingSpeedAndCadence(QBluetoothUuid::CyclingSpeedAndCadence);
for (QLowEnergyService *s : qAsConst(gattCommunicationChannelService)) {
if (s->state() == QLowEnergyService::ServiceDiscovered) {
if(s->serviceUuid() == CyclingSpeedAndCadence) {
qDebug() << "CyclingSpeedAndCadence found";
cadenceService = s;
}
// establish hook into notifications
connect(s, &QLowEnergyService::characteristicChanged, this, &cscbike::characteristicChanged);
connect(s, &QLowEnergyService::characteristicWritten, this, &cscbike::characteristicWritten);
@@ -347,11 +327,7 @@ void cscbike::stateChanged(QLowEnergyService::ServiceState state) {
auto characteristics_list = s->characteristics();
for (const QLowEnergyCharacteristic &c : qAsConst(characteristics_list)) {
if(c.uuid() == QBluetoothUuid((quint16)0x2A5B)) {
qDebug() << "CyclingSpeedAndCadence char found";
cadenceChar = c;
}
qDebug() << QStringLiteral("char uuid") << c.uuid() << QStringLiteral("handle") << c.handle() << QStringLiteral("properties") << c.properties();
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();
@@ -448,8 +424,6 @@ void cscbike::characteristicWritten(const QLowEnergyCharacteristic &characterist
void cscbike::characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) {
qDebug() << QStringLiteral("characteristicRead ") << characteristic.uuid() << newValue.toHex(' ');
characteristicChanged(characteristic, newValue);
}
void cscbike::serviceScanDone(void) {

View File

@@ -47,15 +47,13 @@ class cscbike : public bike {
QTimer *refresh;
QList<QLowEnergyService *> gattCommunicationChannelService;
QLowEnergyService* cadenceService = nullptr;
QLowEnergyCharacteristic cadenceChar;
// QLowEnergyCharacteristic gattNotify1Characteristic;
uint8_t sec1Update = 0;
QByteArray lastPacket;
QDateTime lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
QDateTime lastGoodCadence = QDateTime::currentDateTime();
uint8_t firstStateChanged = 0;
bool charNotified = false;
bool initDone = false;
bool initRequest = false;
@@ -64,8 +62,6 @@ class cscbike : public bike {
bool noHeartService = false;
bool noVirtualDevice = false;
bool readMethod = false;
uint16_t oldLastCrankEventTime = 0;
uint16_t oldCrankRevs = 0;

View File

@@ -1,9 +1,6 @@
#include "dirconmanager.h"
#include <QNetworkInterface>
#include <QSettings>
#include <chrono>
using namespace std::chrono_literals;
#define DM_MACHINE_TYPE_BIKE 1
#define DM_MACHINE_TYPE_TREADMILL 2
@@ -169,10 +166,7 @@ DirconManager::DirconManager(bluetoothdevice *Bike, uint8_t bikeResistanceOffset
QObject::connect(&bikeTimer, &QTimer::timeout, this, &DirconManager::bikeProvider);
QString mac = getMacAddress();
DM_MACHINE_OP(DM_MACHINE_INIT_OP, services, proc_services, type)
if (settings.value(QZSettings::race_mode, QZSettings::default_race_mode).toBool())
bikeTimer.start(100ms);
else
bikeTimer.start(1s);
bikeTimer.start(1000);
}
#define DM_CHAR_NOTIF_NOTIF1_OP(UUID, P1, P2, P3) \

View File

@@ -283,7 +283,6 @@ 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;
@@ -401,7 +400,7 @@ void domyosbike::characteristicChanged(const QLowEnergyCharacteristic &character
CrankRevs++;
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
#ifdef Q_OS_IOS
#ifndef IO_UNDER_QT
@@ -434,7 +433,7 @@ void domyosbike::characteristicChanged(const QLowEnergyCharacteristic &character
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
KCal = kcal;
Distance = distance;

View File

@@ -56,7 +56,8 @@ void domyosrower::writeCharacteristic(uint8_t *data, uint8_t data_len, const QSt
gattCommunicationChannelService->writeCharacteristic(gattWriteCharacteristic, *writeBuffer);
if (!disable_log) {
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') + QStringLiteral(" // ") + info);
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') +
QStringLiteral(" // ") + info);
}
loop.exec();
@@ -195,8 +196,7 @@ void domyosrower::update() {
this->setVirtualDevice(virtualTreadmill, VIRTUAL_DEVICE_MODE::PRIMARY);
} else {
debug("creating virtual bike interface...");
auto virtualBike = new virtualbike(this, noWriteResistance, noHeartService, bikeResistanceOffset,
bikeResistanceGain);
auto virtualBike = new virtualbike(this);
connect(virtualBike, &virtualbike::changeInclination, this,
&domyosrower::changeInclinationRequested);
connect(virtualBike, &virtualbike::changeInclination, this, &domyosrower::changeInclination);
@@ -274,7 +274,6 @@ void domyosrower::serviceDiscovered(const QBluetoothUuid &gatt) {
}
void domyosrower::characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) {
QDateTime now = QDateTime::currentDateTime();
// qDebug() << "characteristicChanged" << characteristic.uuid() << newValue << newValue.length();
Q_UNUSED(characteristic);
QSettings settings;
@@ -361,16 +360,15 @@ void domyosrower::characteristicChanged(const QLowEnergyCharacteristic &characte
Speed = speed;
KCal = kcal;
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
lastRefreshCharacteristicChanged = now;
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
}
double domyosrower::GetSpeedFromPacket(const QByteArray &packet) {
uint16_t convertedData = (packet.at(6) << 8) | packet.at(7);
if (convertedData > 65000 || convertedData == 0 || currentCadence().value() == 0)
return 0;
return (60.0 / (double)(convertedData)) * 30.0;
double data = (double)convertedData / 10.0f;
return data;
}
double domyosrower::GetKcalFromPacket(const QByteArray &packet) {

View File

@@ -158,7 +158,7 @@ void echelonconnectsport::serviceDiscovered(const QBluetoothUuid &gatt) {
resistance_t echelonconnectsport::pelotonToBikeResistance(int pelotonResistance) {
for (resistance_t i = 1; i < max_resistance; i++) {
if (bikeResistanceToPeloton(i) <= pelotonResistance && bikeResistanceToPeloton(i + 1) > pelotonResistance) {
if (bikeResistanceToPeloton(i) <= pelotonResistance && bikeResistanceToPeloton(i + 1) >= pelotonResistance) {
return i;
}
}
@@ -404,8 +404,6 @@ void echelonconnectsport::stateChanged(QLowEnergyService::ServiceState state) {
QSettings settings;
bool virtual_device_enabled =
settings.value(QZSettings::virtual_device_enabled, QZSettings::default_virtual_device_enabled).toBool();
bool virtual_device_rower =
settings.value(QZSettings::virtual_device_rower, QZSettings::default_virtual_device_rower).toBool();
#ifdef Q_OS_IOS
#ifndef IO_UNDER_QT
bool cadence =
@@ -420,19 +418,12 @@ void echelonconnectsport::stateChanged(QLowEnergyService::ServiceState state) {
#endif
#endif
if (virtual_device_enabled) {
if (virtual_device_rower) {
qDebug() << QStringLiteral("creating virtual rower interface...");
auto virtualRower = new virtualrower(this, noWriteResistance, noHeartService);
// connect(virtualRower,&virtualrower::debug ,this,&echelonrower::debug);
this->setVirtualDevice(virtualRower, VIRTUAL_DEVICE_MODE::ALTERNATIVE);
} else {
qDebug() << QStringLiteral("creating virtual bike interface...");
auto virtualBike =
new virtualbike(this, noWriteResistance, noHeartService, bikeResistanceOffset, bikeResistanceGain);
// connect(virtualBike,&virtualbike::debug ,this,&echelonconnectsport::debug);
connect(virtualBike, &virtualbike::changeInclination, this, &echelonconnectsport::changeInclination);
this->setVirtualDevice(virtualBike, VIRTUAL_DEVICE_MODE::PRIMARY);
}
qDebug() << QStringLiteral("creating virtual bike interface...");
auto virtualBike =
new virtualbike(this, noWriteResistance, noHeartService, bikeResistanceOffset, bikeResistanceGain);
// connect(virtualBike,&virtualbike::debug ,this,&echelonconnectsport::debug);
connect(virtualBike, &virtualbike::changeInclination, this, &echelonconnectsport::changeInclination);
this->setVirtualDevice(virtualBike, VIRTUAL_DEVICE_MODE::PRIMARY);
}
}
firstStateChanged = 1;

View File

@@ -28,7 +28,6 @@
#include "bike.h"
#include "virtualbike.h"
#include "virtualrower.h"
#ifdef Q_OS_IOS
#include "ios/lockscreen.h"

View File

@@ -25,7 +25,6 @@ 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;
@@ -237,13 +236,10 @@ void echelonrower::characteristicChanged(const QLowEnergyCharacteristic &charact
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())) / 60000;
}
// instant pace to km/h
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 {
if (((uint8_t)lastPacket.at(14)) > 0)
Speed = (60.0 / (double)((uint8_t)lastPacket.at(14))) * 30.0;
else
Speed = 0;
speedRaw = 0;
}
StrokesLength =
((Speed.value() / 60.0) * 1000.0) /

View File

@@ -76,7 +76,6 @@ class echelonrower : public rower {
bool noWriteResistance = false;
bool noHeartService = false;
metric speedRaw;
#ifdef Q_OS_IOS
lockscreen *h = 0;

View File

@@ -237,7 +237,6 @@ 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 =
@@ -301,10 +300,10 @@ void echelonstride::characteristicChanged(const QLowEnergyCharacteristic &charac
settings.value(QZSettings::weight, QZSettings::default_weight).toFloat() * 3.5) /
200.0) /
(60000.0 / ((double)lastTimeCharacteristicChanged.msecsTo(
now)))); //(( (0.048* Output in watts +1.19) * body weight in
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(now))));
(1000.0 / (lastTimeCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))));
}
if ((uint8_t)newValue.at(1) == 0xD1 && newValue.length() > 11)
@@ -335,7 +334,7 @@ void echelonstride::characteristicChanged(const QLowEnergyCharacteristic &charac
if (m_control->error() != QLowEnergyController::NoError)
qDebug() << QStringLiteral("QLowEnergyController ERROR!!") << m_control->errorString();
lastTimeCharacteristicChanged = now;
lastTimeCharacteristicChanged = QDateTime::currentDateTime();
firstCharacteristicChanged = false;
}

View File

@@ -1,334 +0,0 @@
#include "eliteariafan.h"
#include <QBluetoothLocalDevice>
#include <QDateTime>
#include <QEventLoop>
#include <QFile>
#include <QMetaEnum>
#include <QSettings>
#include <QThread>
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<QLowEnergyService::ServiceState>();
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<void (QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&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<QLowEnergyService::ServiceError>();
emit debug(QStringLiteral("eliteariafan::errorService") + QString::fromLocal8Bit(metaEnum.valueToKey(err)) +
m_control->errorString());
}
void eliteariafan::error(QLowEnergyController::Error err) {
QMetaEnum metaEnum = QMetaEnum::fromType<QLowEnergyController::Error>();
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<void (QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error),
this, &eliteariafan::error);
connect(m_control, &QLowEnergyController::stateChanged, this, &eliteariafan::controllerStateChanged);
connect(m_control,
static_cast<void (QLowEnergyController::*)(QLowEnergyController::Error)>(&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();
}
}

View File

@@ -1,90 +0,0 @@
#ifndef ELITEARIAFAN_H
#define ELITEARIAFAN_H
#include <QBluetoothDeviceDiscoveryAgent>
#include <QtBluetooth/qlowenergyadvertisingdata.h>
#include <QtBluetooth/qlowenergyadvertisingparameters.h>
#include <QtBluetooth/qlowenergycharacteristic.h>
#include <QtBluetooth/qlowenergycharacteristicdata.h>
#include <QtBluetooth/qlowenergycontroller.h>
#include <QtBluetooth/qlowenergydescriptordata.h>
#include <QtBluetooth/qlowenergyservice.h>
#include <QtBluetooth/qlowenergyservicedata.h>
#include <QtCore/qbytearray.h>
#ifndef Q_OS_ANDROID
#include <QtCore/qcoreapplication.h>
#else
#include <QtGui/qguiapplication.h>
#endif
#ifdef Q_OS_IOS
#include "ios/lockscreen.h"
#endif
#include <QtCore/qlist.h>
#include <QtCore/qmutex.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qtimer.h>
#include <QObject>
#include <QTime>
#include "bluetoothdevice.h"
class eliteariafan : public bluetoothdevice {
Q_OBJECT
public:
eliteariafan(bluetoothdevice *parentDevice);
bool connected() override;
private:
QList<QLowEnergyService *> 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

View File

@@ -67,7 +67,6 @@ double elliptical::speedFromWatts() {
if (wattsMetric().value() > 0) {
double vwatts = ((9.8 * weight) * (currentInclination().value() / 100.0));
speed = 210.0 / ((wattsMetric().value() - vwatts) / 75.0 / weight * 1000.0);
speed = 60.0 / speed;
}
return speed;
}
@@ -108,7 +107,6 @@ void elliptical::clearStats() {
Speed.clear(false);
KCal.clear(true);
Distance.clear(true);
Distance1s.clear(true);
Heart.clear(false);
m_jouls.clear(true);
elevationAcc = 0;
@@ -125,7 +123,6 @@ 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);
@@ -140,7 +137,6 @@ 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);

View File

@@ -27,7 +27,7 @@ class elliptical : public bluetoothdevice {
void clearStats() override;
void setPaused(bool p) override;
void setLap() override;
virtual uint16_t watts();
uint16_t watts();
double speedFromWatts();
void setGears(double d);
double gears();

View File

@@ -390,10 +390,7 @@ void eslinkertreadmill::characteristicChanged(const QLowEnergyCharacteristic &ch
}
} else if (treadmill_type == COSTAWAY) {
const double miles = 1.60934;
if(newValue.at(3) == 0xFF)
Speed = 0;
else
Speed = (double)((uint8_t)newValue.at(3)) / 10.0 * miles;
Speed = newValue.at(3) * miles;
Inclination = 0; // this treadmill doesn't have inclination
emit debug(QStringLiteral("Current speed: ") + QString::number(Speed.value()));
}

View File

@@ -32,7 +32,6 @@ 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()));
@@ -51,8 +50,8 @@ void faketreadmill::update() {
cadenceFromAppleWatch();
Distance += ((Speed.value() / (double)3600.0) /
((double)1000.0 / (double)(lastRefreshCharacteristicChanged.msecsTo(now))));
lastRefreshCharacteristicChanged = now;
((double)1000.0 / (double)(lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime()))));
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
// ******************************************* virtual treadmill init *************************************
if (!firstStateChanged && !this->hasVirtualDevice()) {

View File

@@ -376,7 +376,6 @@ 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;
@@ -429,7 +428,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
index += 2;
qDebug() << QStringLiteral("Current Speed: ") + QString::number(Speed.value());
@@ -526,7 +525,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte
200.0) /
(60000.0 /
((double)lastRefreshCharacteristicChanged.msecsTo(
now)))); //(( (0.048* Output in watts +1.19) * body weight in
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in
// kg * 3.5) / 200 ) / 60
}
@@ -539,7 +538,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte
#endif
{
if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) {
Heart = ((double)(((uint8_t)newValue.at(index))));
Heart = ((double)((newValue.at(index))));
// index += 1; // NOTE: clang-analyzer-deadcode.DeadStores
qDebug() << (QStringLiteral("Current Heart: ") + QString::number(Heart.value()));
} else {
@@ -598,7 +597,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte
else*/
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
} else if (newValue.length() == 13) {
@@ -626,7 +625,7 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte
else
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
if (watts())
@@ -635,17 +634,17 @@ void fitplusbike::characteristicChanged(const QLowEnergyCharacteristic &characte
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
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in kg
//* 3.5) / 200 ) / 60
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
if (Cadence.value() > 0) {
CrankRevs++;
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
#ifdef Q_OS_ANDROID
if (settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool())
@@ -919,7 +918,6 @@ void fitplusbike::deviceDiscovered(const QBluetoothDeviceInfo &device) {
bluetoothDevice = device;
if (device.name().startsWith(QStringLiteral("MRK-"))) {
qDebug() << QStringLiteral("merach_MRK workaround enabled!");
merach_MRK = true;
}
@@ -989,91 +987,50 @@ uint16_t fitplusbike::wattsFromResistance(double resistance) {
(double)(currentCadence().value()))) * exp(0.088 * (double)(currentResistance().value())) );*/
const double Epsilon = 4.94065645841247E-324;
const int wattTableFirstDimension = 25;
const int wattTableSecondDimension = 11;
double wattTable[wattTableFirstDimension][wattTableSecondDimension] = {
{Epsilon, 15.0, 15.0, 15.0, 20.0, 30.0, 32.0, 38.0, 44.0, 56.0, 66.0},
{Epsilon, 15.0, 15.0, 15.0, 20.0, 30.0, 32.0, 38.0, 44.0, 56.0, 66.0},
{Epsilon, 16.0, 16.0, 16.0, 22.0, 30.0, 38.0, 45.0, 53.0, 67.0, 79.0},
{Epsilon, 18.0, 18.0, 18.0, 26.0, 34.0, 43.0, 52.0, 62.0, 78.0, 92.0},
{Epsilon, 20.0, 20.0, 20.0, 28.0, 38.0, 48.0, 59.0, 71.0, 89.0, 105.0},
{Epsilon, 23.0, 23.0, 23.0, 32.0, 43.0, 54.0, 66.0, 80.0, 100.0, 118.0},
{Epsilon, 24.0, 24.0, 24.0, 35.0, 46.0, 59.0, 73.0, 89.0, 110.0, 130.0},
{Epsilon, 26.0, 26.0, 26.0, 37.0, 51.0, 65.0, 81.0, 98.0, 122.0, 143.0},
{Epsilon, 28.0, 28.0, 28.0, 41.0, 56.0, 71.0, 88.0, 107.0, 133.0, 156.0},
{Epsilon, 30.0, 30.0, 30.0, 44.0, 60.0, 77.0, 96.0, 116.0, 144.0, 169.0},
{Epsilon, 33.0, 33.0, 33.0, 47.0, 65.0, 83.0, 103.0, 125.0, 155.0, 182.0},
{Epsilon, 34.0, 34.0, 34.0, 50.0, 70.0, 89.0, 110.0, 134.0, 166.0, 195.0},
{Epsilon, 37.0, 37.0, 37.0, 54.0, 74.0, 94.0, 117.0, 143.0, 177.0, 208.0},
{Epsilon, 38.0, 38.0, 38.0, 56.0, 78.0, 100.0, 125.0, 152.0, 188.0, 220.0},
{Epsilon, 41.0, 41.0, 41.0, 60.0, 82.0, 106.0, 132.0, 161.0, 199.0, 233.0},
{Epsilon, 43.0, 43.0, 43.0, 62.0, 86.0, 111.0, 139.0, 170.0, 209.0, 245.0},
{Epsilon, 45.0, 45.0, 45.0, 66.0, 91.0, 117.0, 147.0, 180.0, 220.0, 259.0},
{Epsilon, 48.0, 48.0, 48.0, 70.0, 96.0, 124.0, 155.0, 190.0, 232.0, 273.0},
{Epsilon, 50.0, 50.0, 50.0, 73.0, 101.0, 130.0, 163.0, 200.0, 244.0, 287.0},
{Epsilon, 52.0, 52.0, 52.0, 76.0, 106.0, 136.0, 171.0, 210.0, 256.0, 300.0},
{Epsilon, 54.0, 54.0, 54.0, 80.0, 111.0, 143.0, 179.0, 220.0, 268.0, 314.0},
{Epsilon, 57.0, 57.0, 57.0, 84.0, 116.0, 149.0, 187.0, 230.0, 279.0, 327.0},
{Epsilon, 59.0, 59.0, 59.0, 87.0, 121.0, 155.0, 195.0, 240.0, 290.0, 340.0},
{Epsilon, 62.0, 62.0, 62.0, 91.0, 126.0, 162.0, 203.0, 250.0, 302.0, 353.0},
{Epsilon, 64.0, 64.0, 64.0, 94.0, 130.0, 168.0, 211.0, 260.0, 313.0, 366.0}};
if (merach_MRK) {
const int wattTableFirstDimension = 17;
const int wattTableSecondDimension = 11;
double wattTable[wattTableFirstDimension][wattTableSecondDimension] = {
{Epsilon, 14.3, 28.6, 42.9, 57.2, 71.5, 85.8, 100.1, 114.4, 128.7, 143.0},
{Epsilon, 14.3, 28.6, 42.9, 57.2, 71.5, 85.8, 100.1, 114.4, 128.7, 143.0},
{Epsilon, 16.4, 32.8, 49.2, 65.6, 82.0, 98.4, 114.8, 131.2, 147.6, 164.0},
{Epsilon, 18.7, 37.4, 56.1, 74.8, 93.5, 112.2, 130.9, 149.6, 168.3, 187.0},
{Epsilon, 21.0, 42.0, 63.0, 84.0, 105.0, 126.0, 147.0, 168.0, 189.0, 210.0},
{Epsilon, 23.2, 46.4, 69.6, 92.8, 116.0, 139.2, 162.4, 185.6, 208.8, 232.0},
{Epsilon, 25.3, 50.6, 75.9, 101.2, 126.5, 151.8, 177.1, 202.4, 227.7, 253.0},
{Epsilon, 27.6, 55.2, 82.8, 110.4, 138.0, 165.6, 193.2, 220.8, 248.4, 276.0},
{Epsilon, 30.0, 60.0, 90.0, 120.0, 150.0, 180.0, 210.0, 240.0, 270.0, 300.0},
{Epsilon, 31.9, 63.8, 95.7, 127.6, 159.5, 191.4, 223.3, 255.2, 287.1, 319.0},
{Epsilon, 34.2, 68.4, 102.6, 136.8, 171.0, 205.2, 239.4, 273.6, 307.8, 342.0},
{Epsilon, 36.5, 73.0, 109.5, 146.0, 182.5, 219.0, 255.5, 292.0, 328.5, 365.0},
{Epsilon, 38.5, 77.0, 115.5, 154.0, 192.5, 231.0, 269.5, 308.0, 346.5, 385.0},
{Epsilon, 40.8, 81.6, 122.4, 163.2, 204.0, 244.8, 285.6, 326.4, 367.2, 408.0},
{Epsilon, 43.1, 86.2, 129.3, 172.4, 215.5, 258.6, 301.7, 344.8, 387.9, 431.0},
{Epsilon, 45.1, 90.2, 135.3, 180.4, 225.5, 270.6, 315.7, 360.8, 405.9, 451.0},
{Epsilon, 47.2, 94.4, 141.6, 188.8, 236.0, 283.2, 330.4, 377.6, 424.8, 472.0}};
int level = resistance;
if (level < 0) {
level = 0;
}
if (level >= wattTableFirstDimension) {
level = wattTableFirstDimension - 1;
}
double *watts_of_level = wattTable[level];
int watt_setp = (Cadence.value() / 10.0);
if (watt_setp >= 10) {
return (((double)Cadence.value()) / 100.0) * watts_of_level[wattTableSecondDimension - 1];
}
double watt_base = watts_of_level[watt_setp];
return (((watts_of_level[watt_setp + 1] - watt_base) / 10.0) * ((double)(((int)(Cadence.value())) % 10))) +
watt_base;
} else {
// VirtuFit Etappe 2.0i Spinbike ERG Table #1526
const int wattTableFirstDimension = 25;
const int wattTableSecondDimension = 11;
double wattTable[wattTableFirstDimension][wattTableSecondDimension] = {
{Epsilon, 15.0, 15.0, 15.0, 20.0, 30.0, 32.0, 38.0, 44.0, 56.0, 66.0},
{Epsilon, 15.0, 15.0, 15.0, 20.0, 30.0, 32.0, 38.0, 44.0, 56.0, 66.0},
{Epsilon, 16.0, 16.0, 16.0, 22.0, 30.0, 38.0, 45.0, 53.0, 67.0, 79.0},
{Epsilon, 18.0, 18.0, 18.0, 26.0, 34.0, 43.0, 52.0, 62.0, 78.0, 92.0},
{Epsilon, 20.0, 20.0, 20.0, 28.0, 38.0, 48.0, 59.0, 71.0, 89.0, 105.0},
{Epsilon, 23.0, 23.0, 23.0, 32.0, 43.0, 54.0, 66.0, 80.0, 100.0, 118.0},
{Epsilon, 24.0, 24.0, 24.0, 35.0, 46.0, 59.0, 73.0, 89.0, 110.0, 130.0},
{Epsilon, 26.0, 26.0, 26.0, 37.0, 51.0, 65.0, 81.0, 98.0, 122.0, 143.0},
{Epsilon, 28.0, 28.0, 28.0, 41.0, 56.0, 71.0, 88.0, 107.0, 133.0, 156.0},
{Epsilon, 30.0, 30.0, 30.0, 44.0, 60.0, 77.0, 96.0, 116.0, 144.0, 169.0},
{Epsilon, 33.0, 33.0, 33.0, 47.0, 65.0, 83.0, 103.0, 125.0, 155.0, 182.0},
{Epsilon, 34.0, 34.0, 34.0, 50.0, 70.0, 89.0, 110.0, 134.0, 166.0, 195.0},
{Epsilon, 37.0, 37.0, 37.0, 54.0, 74.0, 94.0, 117.0, 143.0, 177.0, 208.0},
{Epsilon, 38.0, 38.0, 38.0, 56.0, 78.0, 100.0, 125.0, 152.0, 188.0, 220.0},
{Epsilon, 41.0, 41.0, 41.0, 60.0, 82.0, 106.0, 132.0, 161.0, 199.0, 233.0},
{Epsilon, 43.0, 43.0, 43.0, 62.0, 86.0, 111.0, 139.0, 170.0, 209.0, 245.0},
{Epsilon, 45.0, 45.0, 45.0, 66.0, 91.0, 117.0, 147.0, 180.0, 220.0, 259.0},
{Epsilon, 48.0, 48.0, 48.0, 70.0, 96.0, 124.0, 155.0, 190.0, 232.0, 273.0},
{Epsilon, 50.0, 50.0, 50.0, 73.0, 101.0, 130.0, 163.0, 200.0, 244.0, 287.0},
{Epsilon, 52.0, 52.0, 52.0, 76.0, 106.0, 136.0, 171.0, 210.0, 256.0, 300.0},
{Epsilon, 54.0, 54.0, 54.0, 80.0, 111.0, 143.0, 179.0, 220.0, 268.0, 314.0},
{Epsilon, 57.0, 57.0, 57.0, 84.0, 116.0, 149.0, 187.0, 230.0, 279.0, 327.0},
{Epsilon, 59.0, 59.0, 59.0, 87.0, 121.0, 155.0, 195.0, 240.0, 290.0, 340.0},
{Epsilon, 62.0, 62.0, 62.0, 91.0, 126.0, 162.0, 203.0, 250.0, 302.0, 353.0},
{Epsilon, 64.0, 64.0, 64.0, 94.0, 130.0, 168.0, 211.0, 260.0, 313.0, 366.0}};
int level = resistance;
if (level < 0) {
level = 0;
}
if (level >= wattTableFirstDimension) {
level = wattTableFirstDimension - 1;
}
double *watts_of_level = wattTable[level];
int watt_setp = (Cadence.value() / 10.0);
if (watt_setp >= 10) {
return (((double)Cadence.value()) / 100.0) * watts_of_level[wattTableSecondDimension - 1];
}
double watt_base = watts_of_level[watt_setp];
return (((watts_of_level[watt_setp + 1] - watt_base) / 10.0) * ((double)(((int)(Cadence.value())) % 10))) +
watt_base;
int level = resistance;
if (level < 0) {
level = 0;
}
if (level >= wattTableFirstDimension) {
level = wattTableFirstDimension - 1;
}
double *watts_of_level = wattTable[level];
int watt_setp = (Cadence.value() / 10.0);
if (watt_setp >= 10) {
return (((double)Cadence.value()) / 100.0) * watts_of_level[wattTableSecondDimension - 1];
}
double watt_base = watts_of_level[watt_setp];
return (((watts_of_level[watt_setp + 1] - watt_base) / 10.0) * ((double)(((int)(Cadence.value())) % 10))) +
watt_base;
}
resistance_t fitplusbike::resistanceFromPowerRequest(uint16_t power) {

View File

@@ -276,8 +276,7 @@ void fitshowtreadmill::serviceDiscovered(const QBluetoothUuid &gatt) {
QBluetoothUuid nobleproconnect(QStringLiteral("0000ae00-0000-1000-8000-00805f9b34fb"));
emit debug(QStringLiteral("serviceDiscovered ") + gatt.toString() + QStringLiteral(" ") +
QString::number(servRepr));
if ((gatt == nobleproconnect && serviceId.isNull()) || servRepr == 0xfff0 || (servRepr == 0xffe0 && serviceId.isNull())) {
qDebug() << "adding" << gatt.toString() << "as the default service";
if (gatt == nobleproconnect || servRepr == 0xfff0 || (servRepr == 0xffe0 && serviceId.isNull())) {
serviceId = gatt; // NOTE: clazy-rule-of-tow
}
}
@@ -471,11 +470,7 @@ void fitshowtreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha
.toBool())
miles = 1.60934;
if(IS_RUNNING)
Speed = speed * miles;
else
Speed = 0;
Speed = speed * miles;
if (Speed.value() != speed) {
emit speedChanged(speed);
}
@@ -504,9 +499,6 @@ void fitshowtreadmill::characteristicChanged(const QLowEnergyCharacteristic &cha
long appleWatchHeartRate = h->heartRate();
h->setKcal(KCal.value());
h->setDistance(Distance.value());
h->setSpeed(Speed.value());
h->setPower(m_watt.value());
h->setCadence(Cadence.value());
Heart = appleWatchHeartRate;
debug("Current Heart from Apple Watch: " + QString::number(appleWatchHeartRate));
#else

View File

@@ -240,7 +240,6 @@ 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);
@@ -294,7 +293,7 @@ void flywheelbike::characteristicChanged(const QLowEnergyCharacteristic &charact
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
// https://www.facebook.com/groups/149984563348738/permalink/174268944253633/?comment_id=174366620910532&reply_comment_id=174666314213896

View File

@@ -39,12 +39,6 @@ void ftmsbike::writeCharacteristic(uint8_t *data, uint8_t data_len, const QStrin
bool wait_for_response) {
QEventLoop loop;
QTimer timeout;
if(!gattFTMSService) {
qDebug() << QStringLiteral("gattFTMSService is null!");
return;
}
if (wait_for_response) {
connect(gattFTMSService, &QLowEnergyService::characteristicChanged, &loop, &QEventLoop::quit);
timeout.singleShot(300ms, &loop, &QEventLoop::quit);
@@ -58,15 +52,11 @@ void ftmsbike::writeCharacteristic(uint8_t *data, uint8_t data_len, const QStrin
}
writeBuffer = new QByteArray((const char *)data, data_len);
if (gattWriteCharControlPointId.properties() & QLowEnergyCharacteristic::WriteNoResponse) {
gattFTMSService->writeCharacteristic(gattWriteCharControlPointId, *writeBuffer,
QLowEnergyService::WriteWithoutResponse);
} else {
gattFTMSService->writeCharacteristic(gattWriteCharControlPointId, *writeBuffer);
}
gattFTMSService->writeCharacteristic(gattWriteCharControlPointId, *writeBuffer);
if (!disable_log) {
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') + QStringLiteral(" // ") + info);
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') +
QStringLiteral(" // ") + info);
}
loop.exec();
@@ -99,8 +89,7 @@ void ftmsbike::forcePower(int16_t requestPower) {
void ftmsbike::forceResistance(resistance_t requestResistance) {
QSettings settings;
if (!settings.value(QZSettings::ss2k_peloton, QZSettings::default_ss2k_peloton).toBool() &&
resistance_lvl_mode == false) {
if (!settings.value(QZSettings::ss2k_peloton, QZSettings::default_ss2k_peloton).toBool()) {
uint8_t write[] = {FTMS_SET_INDOOR_BIKE_SIMULATION_PARAMS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
double fr = (((double)requestResistance) * bikeResistanceGain) + ((double)bikeResistanceOffset);
@@ -197,7 +186,6 @@ 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;
@@ -247,7 +235,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
index += 2;
emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value()));
@@ -284,20 +272,16 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
}
if (Flags.totDistance) {
/*
* the distance sent from the most trainers is a total distance, so it's useless for QZ
*
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;*/
1000.0;
index += 3;
} else {
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
}
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value()));
if (Flags.resistanceLvl) {
@@ -306,8 +290,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
emit resistanceRead(Resistance.value());
index += 2;
emit debug(QStringLiteral("Current Resistance: ") + QString::number(Resistance.value()));
resistance_received = true;
}
} else {
double ac = 0.01243107769;
double bc = 1.145964912;
double cc = -23.50977444;
@@ -325,13 +308,10 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
(2.0 * ar)) *
settings.value(QZSettings::peloton_gain, QZSettings::default_peloton_gain).toDouble()) +
settings.value(QZSettings::peloton_offset, QZSettings::default_peloton_offset).toDouble();
if (!resistance_received) {
Resistance = m_pelotonResistance;
emit resistanceRead(Resistance.value());
emit debug(QStringLiteral("Current Resistance: ") + QString::number(Resistance.value()));
}
Resistance = m_pelotonResistance;
emit resistanceRead(Resistance.value());
}
}
if (Flags.instantPower) {
if (settings.value(QZSettings::power_sensor_name, QZSettings::default_power_sensor_name)
@@ -368,7 +348,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
200.0) /
(60000.0 /
((double)lastRefreshCharacteristicChanged.msecsTo(
now)))); //(( (0.048* Output in watts +1.19) * body weight in
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in
// kg * 3.5) / 200 ) / 60
}
@@ -381,7 +361,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
#endif
{
if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) {
Heart = ((double)(((uint8_t)newValue.at(index))));
Heart = ((double)((newValue.at(index))));
// index += 1; // NOTE: clang-analyzer-deadcode.DeadStores
emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value()));
} else {
@@ -439,7 +419,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
} else {
Speed = metric::calculateSpeedFromPower(
watts(), Inclination.value(), Speed.value(),
fabs(now.msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
fabs(QDateTime::currentDateTime().msecsTo(Speed.lastChanged()) / 1000.0), this->speedLimit());
}
emit debug(QStringLiteral("Current Speed: ") + QString::number(Speed.value()));
index += 2;
@@ -462,7 +442,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
index += 3;
} else {
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
}
emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value()));
@@ -558,7 +538,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
200.0) /
(60000.0 /
((double)lastRefreshCharacteristicChanged.msecsTo(
now)))); //(( (0.048* Output in watts +1.19) * body weight in
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in
// kg * 3.5) / 200 ) / 60
}
@@ -571,7 +551,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
#endif
{
if (Flags.heartRate && !disable_hr_frommachinery && newValue.length() > index) {
Heart = ((double)(((uint8_t)newValue.at(index))));
Heart = ((double)((newValue.at(index))));
// index += 1; // NOTE: clang-analyzer-deadcode.DeadStores
emit debug(QStringLiteral("Current Heart: ") + QString::number(Heart.value()));
} else {
@@ -600,7 +580,7 @@ void ftmsbike::characteristicChanged(const QLowEnergyCharacteristic &characteris
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
if (heartRateBeltName.startsWith(QStringLiteral("Disabled")) &&
(!heart || Heart.value() == 0 || disable_hr_frommachinery)) {
@@ -779,7 +759,7 @@ void ftmsbike::ftmsCharacteristicChanged(const QLowEnergyCharacteristic &charact
qDebug() << "routing FTMS packet to the bike from virtualbike" << characteristic.uuid() << newValue.toHex(' ');
// handling gears
if (b.at(0) == FTMS_SET_INDOOR_BIKE_SIMULATION_PARAMS) {
if (b.at(0) == 0x11) {
qDebug() << "applying gears mod" << m_gears;
int16_t slope = (((uint8_t)b.at(3)) + (b.at(4) << 8));
if (m_gears != 0) {
@@ -867,9 +847,6 @@ void ftmsbike::deviceDiscovered(const QBluetoothDeviceInfo &device) {
if (bluetoothDevice.name().toUpper().startsWith("SUITO")) {
qDebug() << QStringLiteral("SUITO found");
max_resistance = 16;
} else if ((bluetoothDevice.name().toUpper().startsWith("MAGNUS "))) {
qDebug() << QStringLiteral("MAGNUS found");
resistance_lvl_mode = true;
}
m_control = QLowEnergyController::createCentral(bluetoothDevice, this);

View File

@@ -86,7 +86,7 @@ class ftmsbike : public bike {
QList<QLowEnergyService *> gattCommunicationChannelService;
QLowEnergyCharacteristic gattWriteCharControlPointId;
QLowEnergyService *gattFTMSService = nullptr;
QLowEnergyService *gattFTMSService;
uint8_t sec1Update = 0;
QByteArray lastPacket;
@@ -104,9 +104,6 @@ class ftmsbike : public bike {
bool powerForced = false;
bool resistance_lvl_mode = false;
bool resistance_received = false;
#ifdef Q_OS_IOS
lockscreen *h = 0;
#endif

View File

@@ -54,7 +54,8 @@ void ftmsrower::writeCharacteristic(uint8_t *data, uint8_t data_len, const QStri
gattFTMSService->writeCharacteristic(gattWriteCharControlPointId, *writeBuffer);
if (!disable_log) {
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') + QStringLiteral(" // ") + info);
emit debug(QStringLiteral(" >> ") + writeBuffer->toHex(' ') +
QStringLiteral(" // ") + info);
}
loop.exec();
@@ -136,7 +137,6 @@ 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);
@@ -186,11 +186,9 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri
if (!Flags.moreData) {
if ((WATER_ROWER || DFIT_L_R) && lastStroke.secsTo(now) > 3) {
if (WATER_ROWER && lastStroke.secsTo(QDateTime::currentDateTime()) > 3) {
qDebug() << "Resetting cadence!";
Cadence = 0;
m_watt = 0;
Speed = 0;
} else {
Cadence = ((uint8_t)newValue.at(index)) / cadence_divider;
}
@@ -199,7 +197,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 = now;
lastStroke = QDateTime::currentDateTime();
}
lastStrokesCount = StrokesCount.value();
@@ -231,7 +229,7 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri
index += 3;
} else {
Distance += ((Speed.value() / 3600000.0) *
((double)lastRefreshCharacteristicChanged.msecsTo(now)));
((double)lastRefreshCharacteristicChanged.msecsTo(QDateTime::currentDateTime())));
}
emit debug(QStringLiteral("Current Distance: ") + QString::number(Distance.value()));
@@ -244,10 +242,8 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri
index += 2;
emit debug(QStringLiteral("Current Pace: ") + QString::number(instantPace));
if((DFIT_L_R && Cadence.value() > 0) || !DFIT_L_R) {
Speed = (60.0 / 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()));
}
@@ -265,8 +261,7 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri
((double)(((uint16_t)((uint8_t)newValue.at(index + 1)) << 8) | (uint16_t)((uint8_t)newValue.at(index))));
index += 2;
if (!filterWattNull || watt != 0) {
if((DFIT_L_R && Cadence.value() > 0) || !DFIT_L_R)
m_watt = watt;
m_watt = watt;
}
emit debug(QStringLiteral("Current Watt: ") + QString::number(m_watt.value()));
}
@@ -304,7 +299,7 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri
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
QDateTime::currentDateTime())))); //(( (0.048* Output in watts +1.19) * body weight in
// kg * 3.5) / 200 ) / 60
}
@@ -347,7 +342,7 @@ void ftmsrower::characteristicChanged(const QLowEnergyCharacteristic &characteri
LastCrankEventTime += (uint16_t)(1024.0 / (((double)(Cadence.value())) / 60.0));
}
lastRefreshCharacteristicChanged = now;
lastRefreshCharacteristicChanged = QDateTime::currentDateTime();
if (heartRateBeltName.startsWith(QStringLiteral("Disabled"))) {
update_hr_from_external();
@@ -471,8 +466,6 @@ void ftmsrower::stateChanged(QLowEnergyService::ServiceState state) {
QSettings settings;
bool virtual_device_enabled =
settings.value(QZSettings::virtual_device_enabled, QZSettings::default_virtual_device_enabled).toBool();
bool virtual_device_rower =
settings.value(QZSettings::virtual_device_rower, QZSettings::default_virtual_device_rower).toBool();
#ifdef Q_OS_IOS
#ifndef IO_UNDER_QT
bool cadence =
@@ -488,25 +481,16 @@ void ftmsrower::stateChanged(QLowEnergyService::ServiceState state) {
#endif
#endif
{
if (virtual_device_enabled) {
if (!virtual_device_rower) {
emit debug(QStringLiteral("creating virtual bike interface..."));
emit debug(QStringLiteral("creating virtual bike interface..."));
auto virtualBike = new virtualbike(this, noWriteResistance, noHeartService);
// connect(virtualBike,&virtualbike::debug ,this,&ftmsrower::debug);
this->setVirtualDevice(virtualBike, VIRTUAL_DEVICE_MODE::PRIMARY);
} else {
qDebug() << QStringLiteral("creating virtual rower interface...");
auto virtualRower = new virtualrower(this, noWriteResistance, noHeartService);
// connect(virtualRower,&virtualrower::debug ,this,&echelonrower::debug);
this->setVirtualDevice(virtualRower, VIRTUAL_DEVICE_MODE::PRIMARY);
}
}
auto virtualBike = new virtualbike(this, noWriteResistance, noHeartService);
// connect(virtualBike,&virtualbike::debug ,this,&ftmsrower::debug);
this->setVirtualDevice(virtualBike, VIRTUAL_DEVICE_MODE::PRIMARY);
}
firstStateChanged = 1;
// ********************************************************************************************************
}
firstStateChanged = 1;
// ********************************************************************************************************
}
void ftmsrower::descriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue) {
@@ -580,9 +564,6 @@ void ftmsrower::deviceDiscovered(const QBluetoothDeviceInfo &device) {
} else if (device.name().toUpper().startsWith(QStringLiteral("S4 COMMS"))) {
WATER_ROWER = true;
qDebug() << "WATER_ROWER found!";
} else if (device.name().toUpper().startsWith(QStringLiteral("DFIT-L-R"))) {
DFIT_L_R = true;
qDebug() << "DFIT_L_R found!";
} else if (device.name().toUpper().startsWith(QStringLiteral("PM5"))) {
PM5 = true;
qDebug() << "PM5 found!";

View File

@@ -28,7 +28,6 @@
#include "rower.h"
#include "virtualbike.h"
#include "virtualrower.h"
#ifdef Q_OS_IOS
#include "ios/lockscreen.h"
@@ -70,7 +69,6 @@ class ftmsrower : public rower {
bool PM5 = false;
bool WATER_ROWER = false;
bool DFIT_L_R = false;
QDateTime lastStroke = QDateTime::currentDateTime();
double lastStrokesCount = 0;

View File

@@ -7,16 +7,12 @@
gpx::gpx(QObject *parent) : QObject(parent) {}
QList<gpx_altitude_point_for_treadmill> gpx::open(const QString &gpx, bluetoothdevice::BLUETOOTH_TYPE device_type) {
QList<gpx_altitude_point_for_treadmill> gpx::open(const QString &gpx) {
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;

View File

@@ -29,7 +29,7 @@ class gpx : public QObject {
Q_OBJECT
public:
explicit gpx(QObject *parent = nullptr);
QList<gpx_altitude_point_for_treadmill> open(const QString &gpx, bluetoothdevice::BLUETOOTH_TYPE device_type);
QList<gpx_altitude_point_for_treadmill> open(const QString &gpx);
static void save(const QString &filename, QList<SessionLine> session, bluetoothdevice::BLUETOOTH_TYPE type);
QString getVideoURL() {return videoUrl;}

View File

@@ -5,7 +5,6 @@
#include "localipaddress.h"
#ifdef Q_OS_ANDROID
#include "keepawakehelper.h"
#include <QAndroidJniObject>
#endif
#include "material.h"
#include "qfit.h"
@@ -48,12 +47,23 @@ using namespace std::chrono_literals;
#include <QtAndroid>
#endif
#if __has_include("secret.h")
#include "secret.h"
#else
#define STRAVA_SECRET_KEY test
#if defined(WIN32)
#pragma message("DEFINE STRAVA_SECRET_KEY!!!")
#else
#warning "DEFINE STRAVA_SECRET_KEY!!!"
#endif
#endif
#ifndef STRAVA_CLIENT_ID
#define STRAVA_CLIENT_ID 7976
#if defined(WIN32)
#pragma message("DEFINE STRAVA_CLIENT_ID!!!")
#else
#pragma message "DEFINE STRAVA_CLIENT_ID!!!"
#warning "DEFINE STRAVA_CLIENT_ID!!!"
#endif
#endif
#define _STR(x) #x
@@ -475,9 +485,6 @@ 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)));
QObject::connect(stack, SIGNAL(trainprogram_zwo_loaded(QString)), this, SLOT(trainprogram_zwo_loaded(QString)));
@@ -543,22 +550,6 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) {
}
}
#ifdef Q_OS_ANDROID
// Android 14 restrics access to /Android/data folder
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Android, 14)) {
QDirIterator itAndroid(getAndroidDataAppDir(), QDirIterator::Subdirectories);
QDir().mkdir(getWritableAppDir());
QDir().mkdir(getProfileDir());
while (itAndroid.hasNext()) {
qDebug() << itAndroid.filePath() << itAndroid.fileName() << itAndroid.filePath().replace(itAndroid.path(), "");
if (!QFile(getWritableAppDir() + itAndroid.next().replace(itAndroid.path(), "")).exists()) {
if(QFile::copy(itAndroid.filePath(), getWritableAppDir() + itAndroid.filePath().replace(itAndroid.path(), "")))
QFile::remove(itAndroid.filePath());
}
}
}
#endif
m_speech.setLocale(QLocale::English);
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
@@ -566,12 +557,14 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) {
deviceConnected(b);
#endif
if (settings.value(QZSettings::peloton_bike_ocr, QZSettings::default_peloton_bike_ocr).toBool()) {
// TO RESTORE
if (settings.value(QZSettings::peloton_bike_ocr, QZSettings::default_peloton_bike_ocr).toBool() ||
settings.value(QZSettings::fakedevice_treadmill, QZSettings::default_fakedevice_treadmill).toBool()) {
QBluetoothDeviceInfo b;
deviceConnected(b);
}
#ifndef Q_OS_IOS
#ifdef Q_OS_ANDROID
iphone_browser = new QMdnsEngine::Browser(&iphone_server, "_qz_iphone._tcp.local.", &iphone_cache);
QObject::connect(iphone_browser, &QMdnsEngine::Browser::serviceAdded, [](const QMdnsEngine::Service &service) {
@@ -661,12 +654,8 @@ void homeform::chartSaved(QString fileName) {
if (!stopped)
return;
chartImagesFilenames.append(fileName);
if (chartImagesFilenames.length() >= 9) {
if (chartImagesFilenames.length() >= 8) {
sendMail();
qDebug() << "removing chart images";
for (const QString &f : qAsConst(chartImagesFilenames)) {
QFile::remove(f);
}
chartImagesFilenames.clear();
}
}
@@ -773,7 +762,7 @@ void homeform::peloton_start_workout() {
if (!stravaPelotonActivityName.isEmpty() && !stravaPelotonInstructorName.isEmpty()) {
QString path = getWritableAppDir() + "training/" + workoutNameBasedOnBluetoothDevice() + "/" +
stravaPelotonInstructorName + "/";
QDir().mkpath(path);
QDir().mkdir(path);
lastTrainProgramFileSaved =
path + stravaPelotonActivityName.replace("/", "-") + " - " + stravaPelotonInstructorName + ".xml";
trainProgram->save(lastTrainProgramFileSaved);
@@ -864,13 +853,7 @@ void homeform::pelotonWorkoutChanged(const QString &name, const QString &instruc
QString homeform::getWritableAppDir() {
QString path = QLatin1String("");
#if defined(Q_OS_ANDROID)
// Android 14 restrics access to /Android/data folder
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Android, 14)) {
path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/QZ/";
QDir().mkdir(path);
} else {
path = getAndroidDataAppDir() + "/";
}
path = getAndroidDataAppDir() + "/";
#elif defined(Q_OS_MACOS) || defined(Q_OS_OSX)
path = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + "/";
#elif defined(Q_OS_IOS)
@@ -894,7 +877,7 @@ void homeform::backup() {
QFile::remove(filename);
qfit::save(filename, Session, dev->deviceType(),
qobject_cast<m3ibike *>(dev) ? QFIT_PROCESS_DISTANCENOISE : QFIT_PROCESS_NONE,
stravaPelotonWorkoutType, dev->bluetoothDevice.name());
stravaPelotonWorkoutType);
index++;
if (index > 1) {
@@ -1057,19 +1040,6 @@ void homeform::trainProgramSignals() {
connect(this, &homeform::workoutEventStateChanged, bluetoothManager->device(),
&bluetoothdevice::workoutEventStateChanged);
if (trainProgram) {
setChartIconVisible(trainProgram->powerzoneWorkout());
if (chartFooterVisible()) {
if (trainProgram->powerzoneWorkout()) {
// reloading
setChartFooterVisible(false);
setChartFooterVisible(true);
} else {
setChartFooterVisible(false);
}
}
}
qDebug() << QStringLiteral("trainProgram associated to a device");
} else {
qDebug() << QStringLiteral("trainProgram NOT associated to a device");
@@ -1973,57 +1943,6 @@ void homeform::sortTiles() {
target_pace->setName("T.Pace(m/500m)");
dataList.append(target_pace);
}
if (settings
.value(QZSettings::tile_preset_resistance_1_enabled,
QZSettings::default_tile_preset_resistance_1_enabled)
.toBool() &&
settings.value(QZSettings::tile_preset_resistance_1_order,
QZSettings::default_tile_preset_resistance_1_order)
.toInt() == i) {
preset_resistance_1->setGridId(i);
dataList.append(preset_resistance_1);
}
if (settings
.value(QZSettings::tile_preset_resistance_2_enabled,
QZSettings::default_tile_preset_resistance_2_enabled)
.toBool() &&
settings.value(QZSettings::tile_preset_resistance_2_order,
QZSettings::default_tile_preset_resistance_2_order)
.toInt() == i) {
preset_resistance_2->setGridId(i);
dataList.append(preset_resistance_2);
}
if (settings
.value(QZSettings::tile_preset_resistance_3_enabled,
QZSettings::default_tile_preset_resistance_3_enabled)
.toBool() &&
settings.value(QZSettings::tile_preset_resistance_3_order,
QZSettings::default_tile_preset_resistance_3_order)
.toInt() == i) {
preset_resistance_3->setGridId(i);
dataList.append(preset_resistance_3);
}
if (settings
.value(QZSettings::tile_preset_resistance_4_enabled,
QZSettings::default_tile_preset_resistance_4_enabled)
.toBool() &&
settings.value(QZSettings::tile_preset_resistance_4_order,
QZSettings::default_tile_preset_resistance_4_order)
.toInt() == i) {
preset_resistance_4->setGridId(i);
dataList.append(preset_resistance_4);
}
if (settings
.value(QZSettings::tile_preset_resistance_5_enabled,
QZSettings::default_tile_preset_resistance_5_enabled)
.toBool() &&
settings.value(QZSettings::tile_preset_resistance_5_order,
QZSettings::default_tile_preset_resistance_5_order)
.toInt() == i) {
preset_resistance_5->setGridId(i);
dataList.append(preset_resistance_5);
}
}
} else if (bluetoothManager->device()->deviceType() == bluetoothdevice::ELLIPTICAL) {
for (int i = 0; i < 100; i++) {
@@ -2325,12 +2244,6 @@ void homeform::sortTiles() {
target_pace->setGridId(i);
dataList.append(target_pace);
}
if (settings.value(QZSettings::tile_pace_enabled, true).toBool() &&
settings.value(QZSettings::tile_pace_order, 51).toInt() == i) {
pace->setGridId(i);
dataList.append(pace);
}
}
}
@@ -2436,14 +2349,6 @@ void homeform::deviceConnected(QBluetoothDeviceInfo b) {
if (settings.value(QZSettings::floating_startup, QZSettings::default_floating_startup).toBool()) {
floatingOpen();
}
if (!settings.value(QZSettings::heart_rate_belt_name, QZSettings::default_heart_rate_belt_name)
.toString()
.compare(QZSettings::default_heart_rate_belt_name) &&
!settings.value(QZSettings::ant_heart, QZSettings::default_ant_heart).toBool()) {
QAndroidJniObject::callStaticMethod<void>("org/cagnulen/qdomyoszwift/WearableController", "start",
"(Landroid/content/Context;)V", QtAndroid::androidContext().object());
}
#endif
if (settings.value(QZSettings::gears_restore_value, QZSettings::default_gears_restore_value).toBool()) {
@@ -2907,7 +2812,6 @@ void homeform::Plus(const QString &name) {
} else if (name.contains(QStringLiteral("target_power"))) {
if (bluetoothManager->device()) {
if (bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE) {
m_overridePower = true;
((bike *)bluetoothManager->device())
->changePower(((bike *)bluetoothManager->device())->lastRequestedPower().value() + 10);
if (trainProgram) {
@@ -2953,8 +2857,8 @@ void homeform::pelotonOffset_Minus() { Minus(QStringLiteral("peloton_offset"));
void homeform::bluetoothDeviceConnected(bluetoothdevice *b) {
this->innerTemplateManager->start(b);
this->userTemplateManager->start(b);
#ifndef Q_OS_IOS
// heart rate received from apple watch while QZ is running on a different device via TCP socket (iphone_socket)
#ifdef Q_OS_ANDROID
// heart rate received from apple watch while QZ is running on android via TCP socket (iphone_socket)
connect(this, SIGNAL(heartRate(uint8_t)), b, SLOT(heartRate(uint8_t)));
#endif
}
@@ -3149,7 +3053,6 @@ void homeform::Minus(const QString &name) {
} else if (name.contains(QStringLiteral("target_power"))) {
if (bluetoothManager->device()) {
if (bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE) {
m_overridePower = true;
((bike *)bluetoothManager->device())
->changePower(((bike *)bluetoothManager->device())->lastRequestedPower().value() - 10);
if (trainProgram) {
@@ -3197,8 +3100,6 @@ void homeform::Start_inner(bool send_event_to_device) {
QSettings settings;
qDebug() << QStringLiteral("Start pressed - paused") << paused << QStringLiteral("stopped") << stopped;
m_overridePower = false;
if (settings.value(QZSettings::tts_enabled, QZSettings::default_tts_enabled).toBool())
m_speech.say("Start pressed");
@@ -3303,9 +3204,6 @@ void homeform::StopRequested() {
void homeform::Stop() {
QSettings settings;
m_startRequested = false;
qDebug() << QStringLiteral("Stop pressed - paused") << paused << QStringLiteral("stopped") << stopped;
if (stopped) {
@@ -3356,10 +3254,6 @@ 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) {
@@ -3568,7 +3462,7 @@ void homeform::update() {
else if (next.speed != -1)
nextRows->setValue(QStringLiteral("S") + QString::number(next.speed) + QStringLiteral(" ") +
next.duration.toString(QStringLiteral("mm:ss")));
else if (next.inclination != -200)
else if (next.inclination != -1)
nextRows->setValue(QStringLiteral("I") + QString::number(next.inclination) + QStringLiteral(" ") +
next.duration.toString(QStringLiteral("mm:ss")));
else if (next.power != -1) {
@@ -3641,22 +3535,7 @@ void homeform::update() {
wattKg->setSecondLine(
QStringLiteral("AVG: ") + QString::number(bluetoothManager->device()->wattKg().average(), 'f', 1) +
QStringLiteral("MAX: ") + QString::number(bluetoothManager->device()->wattKg().max(), 'f', 1));
QLocale locale = QLocale::system();
// Format the time based on the locale
QString timeFormat = locale.timeFormat(QLocale::ShortFormat);
bool usesAMPMFormat = timeFormat.toUpper().contains("A");
QDateTime currentTime = QDateTime::currentDateTime();
QString formattedTime;
if (usesAMPMFormat) {
// The locale uses 12-hour format with AM/PM
formattedTime = currentTime.toString("h:mm:ss AP");
} else {
// The locale uses 24-hour format
formattedTime = currentTime.toString("H:mm:ss");
}
datetime->setValue(formattedTime);
datetime->setValue(QTime::currentTime().toString(QStringLiteral("hh:mm:ss")));
if (power5s)
watts = bluetoothManager->device()->wattsMetric().average5s();
else
@@ -3761,46 +3640,29 @@ void homeform::update() {
QStringLiteral(" MAX: ") +
QString::number(((treadmill *)bluetoothManager->device())->currentVerticalOscillation().max(), 'f', 0));
// if there is no training program, the color is based on presets
if (!trainProgram || trainProgram->currentRow().speed == -1) {
if (bluetoothManager->device()->currentSpeed().value() < 9) {
speed->setValueFontColor(QStringLiteral("white"));
this->pace->setValueFontColor(QStringLiteral("white"));
} else if (bluetoothManager->device()->currentSpeed().value() < 10) {
speed->setValueFontColor(QStringLiteral("limegreen"));
this->pace->setValueFontColor(QStringLiteral("limegreen"));
} else if (bluetoothManager->device()->currentSpeed().value() < 11) {
speed->setValueFontColor(QStringLiteral("gold"));
this->pace->setValueFontColor(QStringLiteral("gold"));
} else if (bluetoothManager->device()->currentSpeed().value() < 12) {
speed->setValueFontColor(QStringLiteral("orange"));
this->pace->setValueFontColor(QStringLiteral("orange"));
} else if (bluetoothManager->device()->currentSpeed().value() < 13) {
speed->setValueFontColor(QStringLiteral("darkorange"));
this->pace->setValueFontColor(QStringLiteral("darkorange"));
} else if (bluetoothManager->device()->currentSpeed().value() < 14) {
speed->setValueFontColor(QStringLiteral("orangered"));
this->pace->setValueFontColor(QStringLiteral("orangered"));
} else {
speed->setValueFontColor(QStringLiteral("red"));
this->pace->setValueFontColor(QStringLiteral("red"));
}
if (bluetoothManager->device()->currentSpeed().value() < 9) {
speed->setValueFontColor(QStringLiteral("white"));
this->pace->setValueFontColor(QStringLiteral("white"));
} else if (bluetoothManager->device()->currentSpeed().value() < 10) {
speed->setValueFontColor(QStringLiteral("limegreen"));
this->pace->setValueFontColor(QStringLiteral("limegreen"));
} else if (bluetoothManager->device()->currentSpeed().value() < 11) {
speed->setValueFontColor(QStringLiteral("gold"));
this->pace->setValueFontColor(QStringLiteral("gold"));
} else if (bluetoothManager->device()->currentSpeed().value() < 12) {
speed->setValueFontColor(QStringLiteral("orange"));
this->pace->setValueFontColor(QStringLiteral("orange"));
} else if (bluetoothManager->device()->currentSpeed().value() < 13) {
speed->setValueFontColor(QStringLiteral("darkorange"));
this->pace->setValueFontColor(QStringLiteral("darkorange"));
} else if (bluetoothManager->device()->currentSpeed().value() < 14) {
speed->setValueFontColor(QStringLiteral("orangered"));
this->pace->setValueFontColor(QStringLiteral("orangered"));
} else {
if (bluetoothManager->device()->currentSpeed().value() <= trainProgram->currentRow().upper_speed &&
bluetoothManager->device()->currentSpeed().value() >= trainProgram->currentRow().lower_speed) {
this->target_zone->setValueFontColor(QStringLiteral("limegreen"));
this->pace->setValueFontColor(QStringLiteral("limegreen"));
} else if (bluetoothManager->device()->currentSpeed().value() <=
(trainProgram->currentRow().upper_speed + 0.2) &&
bluetoothManager->device()->currentSpeed().value() >=
(trainProgram->currentRow().lower_speed - 0.2)) {
this->target_zone->setValueFontColor(QStringLiteral("orange"));
this->pace->setValueFontColor(QStringLiteral("orange"));
} else {
this->target_zone->setValueFontColor(QStringLiteral("red"));
this->pace->setValueFontColor(QStringLiteral("red"));
}
speed->setValueFontColor(QStringLiteral("red"));
this->pace->setValueFontColor(QStringLiteral("red"));
}
bluetoothManager->device()->currentSpeed().setColor(speed->valueFontColor());
this->target_pace->setValue(
((treadmill *)bluetoothManager->device())->lastRequestedPace().toString(QStringLiteral("m:ss")));
@@ -3896,14 +3758,6 @@ void homeform::update() {
this->steeringAngle->setValue(
QString::number(((bike *)bluetoothManager->device())->currentSteeringAngle().value(), 'f', 1));
if ((!trainProgram || (trainProgram && !trainProgram->isStarted())) &&
!((bike *)bluetoothManager->device())->ergModeSupportedAvailableByHardware() &&
((bike *)bluetoothManager->device())->lastRequestedPower().value() > 0 && m_overridePower) {
qDebug() << QStringLiteral("using target power tile for ERG workout manually");
((bike *)bluetoothManager->device())
->changePower(((bike *)bluetoothManager->device())->lastRequestedPower().value());
}
} else if (bluetoothManager->device()->deviceType() == bluetoothdevice::ROWING) {
if (bluetoothManager->device()->currentSpeed().value()) {
pace = 10000 / (((rower *)bluetoothManager->device())->currentPace().second() +
@@ -3957,23 +3811,17 @@ void homeform::update() {
}
switch (trainProgram->currentRow().pace_intensity) {
case 0:
this->target_zone->setValue(tr("Rec."));
break;
case 1:
this->target_zone->setValue(tr("Easy"));
break;
case 2:
case 1:
this->target_zone->setValue(tr("Moder."));
break;
case 3:
case 2:
this->target_zone->setValue(tr("Chall."));
break;
case 4:
case 3:
this->target_zone->setValue(tr("Max"));
break;
default:
this->target_zone->setValue(tr("N/A"));
break;
}
}
odometer->setValue(QString::number(bluetoothManager->device()->odometer() * 1000.0, 'f', 0));
@@ -4051,19 +3899,10 @@ 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) {
if (((elliptical *)bluetoothManager->device())->currentSpeed().value() > 2)
this->pace->setValue(
((elliptical *)bluetoothManager->device())->currentPace().toString(QStringLiteral("m:ss")));
else
this->pace->setValue("N/A");
this->pace->setSecondLine(
QStringLiteral("AVG: ") +
((elliptical *)bluetoothManager->device())->averagePace().toString(QStringLiteral("m:ss")) +
QStringLiteral(" MAX: ") +
((elliptical *)bluetoothManager->device())->maxPace().toString(QStringLiteral("m:ss")));
odometer->setValue(QString::number(bluetoothManager->device()->odometer() * unit_conversion, 'f', 2));
resistance = ((elliptical *)bluetoothManager->device())->currentResistance().value();
peloton_resistance = ((elliptical *)bluetoothManager->device())->pelotonResistance().value();
@@ -4116,18 +3955,6 @@ void homeform::update() {
if (trainProgram) {
int8_t lower_requested_peloton_resistance = trainProgram->currentRow().lower_requested_peloton_resistance;
int8_t upper_requested_peloton_resistance = trainProgram->currentRow().upper_requested_peloton_resistance;
double lower_requested_peloton_resistance_to_bike_resistance = 0;
if (bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE)
lower_requested_peloton_resistance_to_bike_resistance =
((bike *)bluetoothManager->device())->pelotonToBikeResistance(lower_requested_peloton_resistance);
else if (bluetoothManager->device()->deviceType() == bluetoothdevice::ROWING)
lower_requested_peloton_resistance_to_bike_resistance =
((rower *)bluetoothManager->device())->pelotonToBikeResistance(lower_requested_peloton_resistance);
else if (bluetoothManager->device()->deviceType() == bluetoothdevice::ELLIPTICAL)
lower_requested_peloton_resistance_to_bike_resistance =
((elliptical *)bluetoothManager->device())
->pelotonToEllipticalResistance(lower_requested_peloton_resistance);
if (lower_requested_peloton_resistance != -1) {
this->target_peloton_resistance->setSecondLine(
QStringLiteral("MIN: ") + QString::number(lower_requested_peloton_resistance, 'f', 0) +
@@ -4142,16 +3969,17 @@ void homeform::update() {
.toBool()) {
if (lower_requested_peloton_resistance == -1) {
this->peloton_resistance->setValueFontColor(QStringLiteral("white"));
} else if (resistance < lower_requested_peloton_resistance_to_bike_resistance) {
// we need to compare the real resistance and not the peloton resistance because most of the bikes
// have a 1:3 conversion so this compare will be always true even if the actual resistance is the
// same #1608
} else if (((int8_t)qRound(peloton_resistance)) < lower_requested_peloton_resistance) {
this->peloton_resistance->setValueFontColor(QStringLiteral("red"));
} else if (((int8_t)qRound(peloton_resistance)) <= upper_requested_peloton_resistance) {
this->peloton_resistance->setValueFontColor(QStringLiteral("limegreen"));
} 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;
@@ -4174,6 +4002,7 @@ void homeform::update() {
} else {
this->cadence->setValueFontColor(QStringLiteral("orange"));
}
bluetoothManager->device()->currentCadence().setColor(this->cadence->valueFontColor());
}
}
@@ -4269,6 +4098,7 @@ 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 ") +
@@ -4466,6 +4296,7 @@ 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: ") +
@@ -4493,11 +4324,9 @@ void homeform::update() {
#ifdef Q_OS_ANDROID
if (settings.value(QZSettings::ant_cadence, QZSettings::default_ant_cadence).toBool() &&
KeepAwakeHelper::antObject(false)) {
double v = bluetoothManager->device()->currentSpeed().value();
v *= settings.value(QZSettings::ant_speed_gain, QZSettings::default_ant_speed_gain).toDouble();
v += settings.value(QZSettings::ant_speed_offset, QZSettings::default_ant_speed_offset).toDouble();
KeepAwakeHelper::antObject(false)->callMethod<void>("setCadenceSpeedPower", "(FII)V", (float)v, (int)watts,
(int)cadence);
KeepAwakeHelper::antObject(false)->callMethod<void>(
"setCadenceSpeedPower", "(FII)V", (float)bluetoothManager->device()->currentSpeed().value(), (int)watts,
(int)cadence);
}
#endif
@@ -4915,16 +4744,6 @@ 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 =
@@ -5163,13 +4982,8 @@ 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()->currentDistance1s().value(),
bluetoothManager->device()->currentSpeed().value(), inclination, bluetoothManager->device()->odometer(),
watts, resistance, peloton_resistance, (uint8_t)bluetoothManager->device()->currentHeart().value(),
pace, cadence, bluetoothManager->device()->calories().value(),
bluetoothManager->device()->elevationGain().value(),
@@ -5186,7 +5000,7 @@ void homeform::update() {
lapTrigger = false;
}
#ifndef Q_OS_IOS
#ifdef Q_OS_ANDROID
if (iphone_socket && iphone_socket->state() == QAbstractSocket::ConnectedState) {
QString toSend =
"SENDER=PAD#HR=" + QString::number(bluetoothManager->device()->currentHeart().value()) +
@@ -5228,67 +5042,11 @@ bool homeform::getLap() {
return true;
}
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<jstring>());
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 = 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();
}
QFileInfo f(fileNameLocal);
QString filename = f.fileName();
QFile fileFile(QQmlFile::urlToLocalFileOrQrc(file));
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(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));
qDebug() << file.fileName();
if (!file.fileName().isEmpty()) {
{
if (previewTrainProgram) {
@@ -5299,7 +5057,7 @@ void homeform::trainprogram_open_clicked(const QUrl &fileName) {
delete trainProgram;
}
trainProgram = trainprogram::load(file.fileName(), bluetoothManager, file.fileName().right(3).toUpper());
trainProgram = trainprogram::load(file.fileName(), bluetoothManager);
QString movieName = file.fileName().left(file.fileName().length() - 3) + "mp4";
if (QFile::exists(movieName)) {
@@ -5316,7 +5074,7 @@ void homeform::trainprogram_open_clicked(const QUrl &fileName) {
trainingProgram()->setVideoAvailable(false);
}
stravaWorkoutName = QFileInfo(file.fileName()).baseName();
stravaWorkoutName = QFileInfo(fileName.fileName()).baseName();
stravaPelotonInstructorName = QStringLiteral("");
emit workoutNameChanged(workoutName());
emit instructorNameChanged(instructorName());
@@ -5336,15 +5094,14 @@ void homeform::trainprogram_preview(const QUrl &fileName) {
qDebug() << QStringLiteral("trainprogram_preview") << fileName;
QFile file(QQmlFile::urlToLocalFileOrQrc(fileName));
QString fileNameLocal = getFileNameFromContentUri(file.fileName());
qDebug() << fileNameLocal;
if (!fileNameLocal.isEmpty()) {
qDebug() << file.fileName();
if (!file.fileName().isEmpty()) {
{
if (previewTrainProgram) {
delete previewTrainProgram;
previewTrainProgram = 0;
}
previewTrainProgram = trainprogram::load(file.fileName(), bluetoothManager, fileNameLocal.right(3).toUpper());
previewTrainProgram = trainprogram::load(file.fileName(), bluetoothManager);
emit previewWorkoutPointsChanged(preview_workout_points());
emit previewWorkoutDescriptionChanged(previewWorkoutDescription());
emit previewWorkoutTagsChanged(previewWorkoutTags());
@@ -5403,7 +5160,7 @@ void homeform::fit_save_clicked() {
qfit::save(filename, Session, dev->deviceType(),
qobject_cast<m3ibike *>(dev) ? QFIT_PROCESS_DISTANCENOISE : QFIT_PROCESS_NONE,
stravaPelotonWorkoutType, workoutName, dev->bluetoothDevice.name());
stravaPelotonWorkoutType, workoutName);
lastFitFileSaved = filename;
QSettings settings;
@@ -5424,7 +5181,7 @@ void homeform::gpx_open_clicked(const QUrl &fileName) {
qDebug() << QStringLiteral("gpx_open_clicked") << fileName;
QFile file(QQmlFile::urlToLocalFileOrQrc(fileName));
qDebug() << file.fileName();
stravaWorkoutName = QFileInfo(file.fileName()).baseName();
if (!file.fileName().isEmpty()) {
{
@@ -5436,7 +5193,7 @@ void homeform::gpx_open_clicked(const QUrl &fileName) {
// KML to GPX https://www.gpsvisualizer.com/elevation
gpx g;
QList<trainrow> list;
auto g_list = g.open(file.fileName(), bluetoothManager->device() ? bluetoothManager->device()->deviceType() : bluetoothdevice::BIKE);
auto g_list = g.open(file.fileName());
if (bluetoothManager->device())
bluetoothManager->device()->setGPXFile(file.fileName());
gpx_altitude_point_for_treadmill last;
@@ -5506,7 +5263,7 @@ void homeform::gpxpreview_open_clicked(const QUrl &fileName) {
if (!file.fileName().isEmpty()) {
gpx g;
auto g_list = g.open(file.fileName(), bluetoothManager->device() ? bluetoothManager->device()->deviceType() : bluetoothdevice::BIKE);
auto g_list = g.open(file.fileName());
gpx_preview.clearPath();
for (const auto &p : g_list) {
gpx_preview.addCoordinate(QGeoCoordinate(p.latitude, p.longitude, p.elevation));
@@ -5669,10 +5426,6 @@ bool homeform::strava_upload_file(const QByteArray &data, const QString &remoten
activityNamePart.setHeader(QNetworkRequest::ContentDispositionHeader,
QVariant(QStringLiteral("form-data; name=\"name\"")));
QString prefix = QStringLiteral("");
if (settings.value(QZSettings::strava_date_prefix, QZSettings::default_strava_date_prefix).toBool())
prefix = " " + QDate::currentDate().toString(Qt::TextDate);
// use metadata config if the user selected it
QString activityName =
QStringLiteral(" ") + settings.value(QZSettings::strava_suffix, QZSettings::default_strava_suffix).toString();
@@ -5685,11 +5438,11 @@ bool homeform::strava_upload_file(const QByteArray &data, const QString &remoten
pelotonHandler->current_ride_id;
} else {
if (bluetoothManager->device()->deviceType() == bluetoothdevice::TREADMILL) {
activityName = prefix + QStringLiteral("Run") + activityName;
activityName = QStringLiteral("Run") + activityName;
} else if (bluetoothManager->device()->deviceType() == bluetoothdevice::ROWING) {
activityName = prefix + QStringLiteral("Row") + activityName;
activityName = QStringLiteral("Row") + activityName;
} else {
activityName = prefix + QStringLiteral("Ride") + activityName;
activityName = QStringLiteral("Ride") + activityName;
}
}
activityNamePart.setHeader(QNetworkRequest::ContentTypeHeader,
@@ -5931,7 +5684,7 @@ QOAuth2AuthorizationCodeFlow *homeform::strava_connect() {
#elif defined(WIN32)
#pragma message("DEFINE STRAVA_SECRET_KEY!!!")
#else
#pragma message "DEFINE STRAVA_SECRET_KEY!!!"
#warning "DEFINE STRAVA_SECRET_KEY!!!"
#endif
strava->setModifyParametersFunction(
buildModifyParametersFunction(QUrl(QLatin1String("")), QUrl(QLatin1String(""))));
@@ -5988,14 +5741,6 @@ void homeform::setVideoIconVisible(bool value) {
emit videoIconVisibleChanged(m_VideoIconVisible);
}
bool homeform::chartIconVisible() { return m_ChartIconVisible; }
void homeform::setChartIconVisible(bool value) {
m_ChartIconVisible = value;
emit chartIconVisibleChanged(m_ChartIconVisible);
}
int homeform::videoPosition() { return m_VideoPosition; }
void homeform::setVideoPosition(int value) {
@@ -6052,7 +5797,7 @@ void homeform::sendMail() {
SmtpClient smtp(STRINGIFY(SMTP_SERVER), 587, SmtpClient::TlsConnection);
connect(&smtp, SIGNAL(smtpError(SmtpClient::SmtpError)), this, SLOT(smtpError(SmtpClient::SmtpError)));
#else
#pragma message "stmp server is unset!"
#warning "stmp server is unset!"
SmtpClient smtp(QLatin1String(""), 25, SmtpClient::TlsConnection);
return;
#endif
@@ -6064,7 +5809,7 @@ void homeform::sendMail() {
#define STRINGIFY(x) _STR(x)
smtp.setUser(STRINGIFY(SMTP_USERNAME));
#else
#pragma message "smtp username is unset!"
#warning "smtp username is unset!"
return;
#endif
#ifdef SMTP_PASSWORD
@@ -6072,7 +5817,7 @@ void homeform::sendMail() {
#define STRINGIFY(x) _STR(x)
smtp.setPassword(STRINGIFY(SMTP_PASSWORD));
#else
#pragma message "smtp password is unset!"
#warning "smtp password is unset!"
return;
#endif
@@ -6146,30 +5891,8 @@ void homeform::sendMail() {
QStringLiteral("Moving Time: ") + bluetoothManager->device()->movingTime().toString() + QStringLiteral("\n");
textMessage += QStringLiteral("Weight Loss (") + weightLossUnit + "): " + QString::number(WeightLoss, 'f', 2) +
QStringLiteral("\n");
textMessage += QStringLiteral("Estimated VO2Max: ") + QString::number(metric::calculateVO2Max(&Session), 'f', 0) +
textMessage += QStringLiteral("Estimated VO2Max: ") + QString::number(metric::calculateVO2Max(&Session), 'f', 1) +
QStringLiteral("\n");
double peak = metric::powerPeak(&Session, 5);
double weightKg = settings.value(QZSettings::weight, QZSettings::default_weight).toFloat();
textMessage += QStringLiteral("5 Seconds Power: ") + QString::number(peak, 'f', 0) +
QStringLiteral("W ") + QString::number(peak/weightKg, 'f', 1) + QStringLiteral("W/Kg\n");
peak = metric::powerPeak(&Session, 60);
textMessage += QStringLiteral("1 Minute Power: ") + QString::number(peak, 'f', 0) +
QStringLiteral("W ") + QString::number(peak/weightKg, 'f', 1) + QStringLiteral("W/Kg\n");
peak = metric::powerPeak(&Session, 5 * 60);
textMessage += QStringLiteral("5 Minutes Power: ") + QString::number(peak, 'f', 0) +
QStringLiteral("W ") + QString::number(peak/weightKg, 'f', 1) + QStringLiteral("W/Kg\n");
// FTP
double ftpSetting = settings.value(QZSettings::ftp, QZSettings::default_ftp).toDouble();
peak = (metric::powerPeak(&Session, 20 * 60) * 0.95) * 0.95;
textMessage += QStringLiteral("Estimated FTP: ") + QString::number(peak, 'f', 0) +
QStringLiteral("W ");
if(peak > ftpSetting) {
textMessage += QStringLiteral(" FTP IMPROVED +") + QString::number(peak - ftpSetting, 'f', 0) +
QStringLiteral("W!");
}
textMessage += QStringLiteral("\n");
if (bluetoothManager->device()->deviceType() == bluetoothdevice::BIKE) {
textMessage += QStringLiteral("Average Cadence: ") +
QString::number(((bike *)bluetoothManager->device())->currentCadence().average(), 'f', 0) +
@@ -6238,10 +5961,6 @@ void homeform::sendMail() {
}
}
#ifdef SMTP_SERVER
textMessage += QStringLiteral("\n\nSMTP server: ") + QString(STRINGIFY(SMTP_SERVER));
#endif
text.setText(textMessage);
message.addPart(&text);
@@ -6422,14 +6141,10 @@ void homeform::saveSettings(const QUrl &filename) {
}
void homeform::loadSettings(const QUrl &filename) {
QFile file(QQmlFile::urlToLocalFileOrQrc(filename));
copyAndroidContentsURI(filename, "settings");
qDebug() << "homeform::loadSettings" << file.fileName();
qDebug() << "homeform::loadSettings" << filename;
QSettings settings;
QSettings settings2Load(file.fileName(), QSettings::IniFormat);
QSettings settings2Load(filename.toLocalFile(), QSettings::IniFormat);
auto settings2LoadAllKeys = settings2Load.allKeys();
for (const QString &s : qAsConst(settings2LoadAllKeys)) {
if (!s.contains(QZSettings::cryptoKeySettingsProfiles)) {

View File

@@ -6,9 +6,6 @@
#include "fit_profile.hpp"
#include "gpx.h"
#include "peloton.h"
#include "qmdnsengine/browser.h"
#include "qmdnsengine/cache.h"
#include "qmdnsengine/resolver.h"
#include "screencapture.h"
#include "sessionline.h"
#include "smtpclient/src/SmtpMime"
@@ -23,17 +20,9 @@
#include <QQuickItem>
#include <QQuickItemGrabResult>
#include <QTextToSpeech>
#if __has_include("secret.h")
#include "secret.h"
#else
#define STRAVA_SECRET_KEY test
#if defined(WIN32)
#pragma message("DEFINE STRAVA_SECRET_KEY!!!")
#else
#warning "DEFINE STRAVA_SECRET_KEY!!!"
#endif
#endif
#include "qmdnsengine/browser.h"
#include "qmdnsengine/cache.h"
#include "qmdnsengine/resolver.h"
class DataObject : public QObject {
@@ -148,9 +137,6 @@ class homeform : public QObject {
Q_PROPERTY(bool mapsVisible READ mapsVisible NOTIFY mapsVisibleChanged WRITE setMapsVisible)
Q_PROPERTY(bool videoIconVisible READ videoIconVisible NOTIFY videoIconVisibleChanged WRITE setVideoIconVisible)
Q_PROPERTY(bool videoVisible READ videoVisible NOTIFY videoVisibleChanged WRITE setVideoVisible)
Q_PROPERTY(bool chartIconVisible READ chartIconVisible NOTIFY chartIconVisibleChanged WRITE setChartIconVisible)
Q_PROPERTY(
bool chartFooterVisible READ chartFooterVisible NOTIFY chartFooterVisibleChanged WRITE setChartFooterVisible)
Q_PROPERTY(QUrl videoPath READ videoPath NOTIFY videoPathChanged)
Q_PROPERTY(int videoPosition READ videoPosition NOTIFY videoPositionChanged WRITE setVideoPosition)
Q_PROPERTY(double videoRate READ videoRate NOTIFY videoRateChanged WRITE setVideoRate)
@@ -199,7 +185,6 @@ class homeform : public QObject {
QObject *stack = rootObject;
screenCapture s(reinterpret_cast<QQuickView *>(stack));
s.capture(filenameScreenshot);
chartImagesFilenames.append(filenameScreenshot);
}
Q_INVOKABLE void save_screenshot_chart(QQuickItem *item, QString filename) {
@@ -399,8 +384,6 @@ class homeform : public QObject {
bool mapsVisible();
bool videoIconVisible();
bool videoVisible() { return m_VideoVisible; }
bool chartIconVisible();
bool chartFooterVisible() { return m_ChartFooterVisible; }
int videoPosition();
double videoRate();
double currentSpeed() {
@@ -432,15 +415,10 @@ class homeform : public QObject {
}
void setLicensePopupVisible(bool value);
void setVideoIconVisible(bool value);
void setChartIconVisible(bool value);
void setVideoVisible(bool value) {
m_VideoVisible = value;
emit videoVisibleChanged(m_VideoVisible);
}
void setChartFooterVisible(bool value) {
m_ChartFooterVisible = value;
emit chartFooterVisibleChanged(m_ChartFooterVisible);
}
void setVideoPosition(int position); // on startup
void videoSeekPosition(int ms); // in realtime
void setVideoRate(double rate);
@@ -550,12 +528,73 @@ class homeform : public QObject {
return false;
}
bool trainProgramLoadedWithVideo() { return (trainProgram && trainProgram->videoAvailable); }
bool trainProgramLoadedWithVideo() {
return (trainProgram && trainProgram->videoAvailable);
}
QString getStravaAuthUrl() { return stravaAuthUrl; }
bool stravaWebVisible() { return stravaAuthWebVisible; }
trainprogram *trainingProgram() { return trainProgram; }
private:
static homeform *m_singleton;
TemplateInfoSenderBuilder *userTemplateManager = nullptr;
TemplateInfoSenderBuilder *innerTemplateManager = nullptr;
QList<QObject *> dataList;
QList<SessionLine> Session;
bluetooth *bluetoothManager;
QQmlApplicationEngine *engine;
trainprogram *trainProgram = nullptr;
trainprogram *previewTrainProgram = nullptr;
QString backupFitFileName =
QStringLiteral("QZ-backup-") +
QDateTime::currentDateTime().toString().replace(QStringLiteral(":"), QStringLiteral("_")) +
QStringLiteral(".fit");
int m_topBarHeight = 120;
QString m_info = QStringLiteral("Connecting...");
bool m_labelHelp = true;
bool m_generalPopupVisible = false;
bool m_LicensePopupVisible = false;
bool m_MapsVisible = false;
bool m_VideoIconVisible = false;
bool m_VideoVisible = false;
int m_VideoPosition = 0;
double m_VideoRate = 1;
QOAuth2AuthorizationCodeFlow *strava = nullptr;
QNetworkAccessManager *manager = nullptr;
QOAuthHttpServerReplyHandler *stravaReplyHandler = nullptr;
bool paused = false;
bool stopped = false;
bool lapTrigger = false;
peloton *pelotonHandler = nullptr;
bool m_pelotonAskStart = false;
QString m_pelotonProvider = "";
QString m_toastRequested = "";
int m_pelotonLoginState = -1;
int m_pzpLoginState = -1;
QString stravaPelotonActivityName;
QString stravaPelotonInstructorName;
QString stravaWorkoutName = "";
QUrl movieFileName;
FIT_SPORT stravaPelotonWorkoutType = FIT_SPORT_INVALID;
QString activityDescription;
QString pelotonAskedName = QStringLiteral("");
QString pelotonAskedInstructor = QStringLiteral("");
QString pelotonAbortedName = QStringLiteral("");
QString pelotonAbortedInstructor = QStringLiteral("");
QString lastFitFileSaved = QLatin1String("");
QString lastTrainProgramFileSaved = QLatin1String("");
QList<QString> chartImagesFilenames;
bool m_autoresistance = true;
bool m_stopRequested = false;
bool m_startRequested = false;
DataObject *speed;
DataObject *inclination;
DataObject *cadence;
@@ -618,68 +657,6 @@ class homeform : public QObject {
DataObject *preset_inclination_5;
DataObject *pace_last500m;
private:
static homeform *m_singleton;
TemplateInfoSenderBuilder *userTemplateManager = nullptr;
TemplateInfoSenderBuilder *innerTemplateManager = nullptr;
QList<QObject *> dataList;
QList<SessionLine> Session;
bluetooth *bluetoothManager;
QQmlApplicationEngine *engine;
trainprogram *trainProgram = nullptr;
trainprogram *previewTrainProgram = nullptr;
QString backupFitFileName =
QStringLiteral("QZ-backup-") +
QDateTime::currentDateTime().toString().replace(QStringLiteral(":"), QStringLiteral("_")) +
QStringLiteral(".fit");
int m_topBarHeight = 120;
QString m_info = QStringLiteral("Connecting...");
bool m_labelHelp = true;
bool m_generalPopupVisible = false;
bool m_LicensePopupVisible = false;
bool m_MapsVisible = false;
bool m_VideoIconVisible = false;
bool m_VideoVisible = false;
bool m_ChartFooterVisible = false;
bool m_ChartIconVisible = false;
int m_VideoPosition = 0;
double m_VideoRate = 1;
QOAuth2AuthorizationCodeFlow *strava = nullptr;
QNetworkAccessManager *manager = nullptr;
QOAuthHttpServerReplyHandler *stravaReplyHandler = nullptr;
bool paused = false;
bool stopped = false;
bool lapTrigger = false;
peloton *pelotonHandler = nullptr;
bool m_pelotonAskStart = false;
QString m_pelotonProvider = "";
QString m_toastRequested = "";
int m_pelotonLoginState = -1;
int m_pzpLoginState = -1;
QString stravaPelotonActivityName;
QString stravaPelotonInstructorName;
QString stravaWorkoutName = "";
QUrl movieFileName;
FIT_SPORT stravaPelotonWorkoutType = FIT_SPORT_INVALID;
QString activityDescription;
QString pelotonAskedName = QStringLiteral("");
QString pelotonAskedInstructor = QStringLiteral("");
QString pelotonAbortedName = QStringLiteral("");
QString pelotonAbortedInstructor = QStringLiteral("");
QString lastFitFileSaved = QLatin1String("");
QString lastTrainProgramFileSaved = QLatin1String("");
QList<QString> chartImagesFilenames;
bool m_autoresistance = true;
bool m_stopRequested = false;
bool m_startRequested = false;
bool m_overridePower = false;
QTimer *timer;
QTimer *backupTimer;
@@ -695,9 +672,6 @@ class homeform : public QObject {
static quint64 cryptoKeySettingsProfiles();
static QString copyAndroidContentsURI(QUrl file, QString subfolder);
static QString getFileNameFromContentUri(const QString &uriString);
int16_t fanOverride = 0;
void update();
@@ -722,17 +696,15 @@ class homeform : public QObject {
#ifdef Q_OS_ANDROID
bool floating_open = false;
#endif
#ifndef Q_OS_IOS
QMdnsEngine::Browser *iphone_browser = nullptr;
QMdnsEngine::Resolver *iphone_resolver = nullptr;
QMdnsEngine::Browser* iphone_browser = nullptr;
QMdnsEngine::Resolver* iphone_resolver = nullptr;
QMdnsEngine::Server iphone_server;
QMdnsEngine::Cache iphone_cache;
QTcpSocket *iphone_socket = nullptr;
QTcpSocket* iphone_socket = nullptr;
QMdnsEngine::Service iphone_service;
QHostAddress iphone_address;
#endif
#endif
public slots:
void aboutToQuit();
@@ -762,9 +734,6 @@ 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);
void trainprogram_zwo_loaded(const QString &comp);
@@ -835,8 +804,6 @@ class homeform : public QObject {
void videoPositionChanged(int value);
void videoPathChanged(QUrl value);
void videoRateChanged(double value);
void chartIconVisibleChanged(bool value);
void chartFooterVisibleChanged(bool value);
void currentSpeedChanged(double value);
void mapsVisibleChanged(bool value);
void autoResistanceChanged(bool value);

Some files were not shown because too many files have changed in this diff Show More