Compare commits

..

2 Commits

Author SHA1 Message Date
Roberto Viola
a5565f5913 Update build_ios.yml 2021-07-27 16:09:14 +02:00
Roberto Viola
b4e41131a9 Create build_ios.yml 2021-07-27 16:07:40 +02:00
710 changed files with 72682 additions and 167690 deletions

View File

@@ -32,10 +32,5 @@ If applicable, add screenshots to help explain your problem.
- OS: [e.g. iOS8.1]
- Version [e.g. 22]
**Append a debug log**
Follow this guide https://github.com/cagnulein/qdomyos-zwift/wiki/How-do-i-get-the-debug-log-in-case-something-doesn't-work%3F
**Additional context**
Add any other context about the problem here.

17
.github/stale.yml vendored
View File

@@ -1,17 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 15
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
#closeComment: false

43
.github/workflows/build_ios.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
# This is a basic workflow to help you get started with Actions
name: build-ios
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the master branch
#push:
# branches: [ master ]
#pull_request:
# branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build: # make sure build/ci work properly
runs-on: macOS-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v2
- uses: Apple-Actions/import-codesign-certs@v1
with:
p12-file-base64: ${{ secrets.CERTIFICATES_FILE_BASE64 }}
p12-password: ${{ secrets.CERTIFICATES_PASSWORD }}
- uses: Apple-Actions/download-provisioning-profiles@v1
with:
bundle-id: org.cagnulein.qdomyoszwift
issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
api-key-id: ${{ secrets.APPSTORE_KEY_ID }}
api-private-key: ${{ secrets.APPSTORE_PRIVATE_KEY }}
- name: "#️⃣ Generate Build Number"
id: buildnumber
uses: einaregilsson/build-number@v2
with:
token: ${{ secrets.github_token }}
- run: ./Build
# - uses: Apple-Actions/upload-testflight-build@master
# with:
# app-path: .build/Artifacts/Example-iOS.ipa/Example-iOS.ipa
# issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }}
# api-key-id: ${{ secrets.APPSTORE_KEY_ID }}
# api-private-key: ${{ secrets.APPSTORE_PRIVATE_KEY }}

View File

@@ -8,7 +8,6 @@ env:
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
workflow_dispatch:
push:
branches: [ master, github-workflow-playground ]
pull_request:
@@ -18,86 +17,6 @@ on:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
window-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: microsoft/MSIX-Toolkit
path: "src/MSIX-Toolkit/"
ref: b82af826d29e93e4c85d34fad8a405b6c49905e7
- uses: msys2/setup-msys2@v2
with:
install: mingw-w64-x86_64-toolchain
msystem: mingw64
release: false
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.9
with:
cmake-version: '3.20.x'
- name: Install Qt
uses: jurplel/install-qt-action@v2
with:
version: '5.15.2'
host: 'windows'
modules: 'qtnetworkauth qtcharts'
target: "desktop"
arch: win64_mingw81
dir: "${{github.workspace}}/qt/"
install-deps: "true"
- name: Build
run: |
cd src
qmake
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
make -j8
cd debug
mkdir output
mkdir appx
cp qdomyos-zwift.exe output/
cd output
windeployqt --qmldir ../../ qdomyos-zwift.exe
cp "${{github.workspace}}/qt/Qt/5.15.2/mingw81_64/bin/libwinpthread-1.dll" .
cp "${{github.workspace}}/qt/Qt/5.15.2/mingw81_64/bin/libgcc_s_seh-1.dll" .
cp "${{github.workspace}}/qt/Qt/5.15.2/mingw81_64/bin/libstdc++-6.dll" .
cp ../../../icons/iOS/iTunesArtwork@2x.png .
cp ../../AppxManifest.xml .
cd ..
cd appx
#../../MSIX-Toolkit/WindowsSDK/10/10.0.20348.0/x64/makeappx.exe pack /d ../output/ /p qz
- name: Archive windows binary
uses: actions/upload-artifact@v2
with:
name: windows-binary
path: src/debug/output
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
@@ -131,25 +50,9 @@ jobs:
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"
- name: Install packages required to run QZ inside workflow
run: sudo apt update -y && sudo apt-get install -y qt5-default qtquickcontrols2-5-dev libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-default libqt5networkauth5-dev libqt5websockets5* libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev
- name: Install Qt
uses: jurplel/install-qt-action@v2
with:
version: '5.15.2'
host: 'linux'
modules: 'qtnetworkauth qtcharts'
run: sudo apt-get install -y qt5-default libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-default libqt5networkauth5-dev libqt5websockets5* libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev
- name: Compile Linux Desktop
run: cd src; qmake; make -j8
@@ -160,14 +63,14 @@ jobs:
name: linux-desktop-binary
path: src/qdomyos-zwift
# - name: Test Peloton API
# if: github.event_name == 'push' || github.event_name == 'schedule'
# run: cd /home/runner/work/qdomyos-zwift/qdomyos-zwift/src/; ./qdomyos-zwift -test-peloton -peloton-username ${{ secrets.peloton_username }} -peloton-password ${{ secrets.peloton_password }}
# timeout-minutes: 2
- name: Test Peloton API
if: github.event_name == 'push' || github.event_name == 'schedule'
run: cd /home/runner/work/qdomyos-zwift/qdomyos-zwift/src/; ./qdomyos-zwift -test-peloton -peloton-username ${{ secrets.peloton_username }} -peloton-password ${{ secrets.peloton_password }}
timeout-minutes: 2
# - name: Test Home Fitness Buddy API
# run: cd /home/runner/work/qdomyos-zwift/qdomyos-zwift/src/; ./qdomyos-zwift -test-hfb
# timeout-minutes: 2
- name: Test Home Fitness Buddy API
run: cd /home/runner/work/qdomyos-zwift/qdomyos-zwift/src/; ./qdomyos-zwift -test-hfb
timeout-minutes: 2
# - uses: actions/checkout@v2
# with:

12
.gitignore vendored
View File

@@ -18,15 +18,9 @@ src/build/*
src/debug-*
src/secret.h
*.swo
*.swp
build-qdomyos-zwift-Android_Qt_5_15_2_Clang_Multi_Abi-Debug/*
**/node_modules/*
*.pro.user
template-examples/youtube-viewer/node_modules/*
template-examples/youtube-viewer/*.json
template-examples/youtube-viewer/.eslintrc.js
@@ -39,9 +33,3 @@ template-examples/train-program-saver/*.json
template-examples/train-program-saver/.eslintrc.js
template-examples/train-program-saver/.jshintrc
template-examples/train-program-saver/debug.js
# Qt-es
*.pro.user
*build-*
!build-qdomyos-zwift-Qt_*_for_iOS-Debug # Needed for Apple Watch
src/inner_templates/googlemaps/cesium-key.js

7
.gitmodules vendored
View File

@@ -3,9 +3,4 @@
url = https://github.com/KDAB/android_openssl.git
[submodule "src/smtpclient"]
path = src/smtpclient
url = https://github.com/cagnulein/SmtpClient-for-Qt.git
branch = cagnulein-patch-2
[submodule "src/qmdnsengine"]
path = src/qmdnsengine
url = https://github.com/cagnulein/qmdnsengine.git
branch = zwift
url = https://github.com/bluetiger9/SmtpClient-for-Qt.git

View File

@@ -1,8 +1,6 @@
# qdomyos-zwift
Zwift bridge for Treadmills and Bike!
## QZ is not affiliated with or endorsed by any subscription service or maker of exercise equipment.
[<img src="docs/img/google_play.png">](https://play.google.com/store/apps/details?id=org.cagnulen.qdomyoszwift&fbclid=IwAR3CVoYb0scvGf7gb0Y20VFh5Na5fDWwe7VACk-2c45Tm0x5s8sXpIGhGyw)
[<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>

View File

@@ -54,10 +54,8 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<RemoteRunnable
runnableDebuggingMode = "2"
BundleIdentifier = "com.apple.Carousel"
RemotePath = "/qdomyoszwift">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "876E4E102594747F00BD5714"
@@ -65,7 +63,7 @@
BlueprintName = "watchkit"
ReferencedContainer = "container:qdomyoszwift.xcodeproj">
</BuildableReference>
</RemoteRunnable>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
@@ -73,10 +71,8 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<RemoteRunnable
runnableDebuggingMode = "2"
BundleIdentifier = "com.apple.Carousel"
RemotePath = "/qdomyoszwift">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "876E4E102594747F00BD5714"
@@ -84,16 +80,7 @@
BlueprintName = "watchkit"
ReferencedContainer = "container:qdomyoszwift.xcodeproj">
</BuildableReference>
</RemoteRunnable>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "876E4E102594747F00BD5714"
BuildableName = "watchkit.app"
BlueprintName = "watchkit"
ReferencedContainer = "container:qdomyoszwift.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">

View File

@@ -193,38 +193,6 @@
endingLineNumber = "57"
landmarkName = "BLEPeripheralManager"
landmarkType = "3">
<Locations>
<Location
uuid = "16D24B27-D0FB-4EC3-BAE8-56101FE7949B - 1c798ec95ff8d4b7"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "qdomyoszwift.BLEPeripheralManager.crankRevolutions.modify : Swift.Optional&lt;Swift.UInt16&gt;"
moduleName = "qdomyoszwift"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/cagnulein/qdomyos-zwift/build-qdomyos-zwift-Qt_5_15_2_for_iOS-Debug/%3Ccompiler-generated%3E"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "0"
endingLineNumber = "0"
offsetFromSymbolStart = "16">
</Location>
<Location
uuid = "16D24B27-D0FB-4EC3-BAE8-56101FE7949B - 5ebbef0dc9913f07"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "qdomyoszwift.BLEPeripheralManager.init() -&gt; qdomyoszwift.BLEPeripheralManager"
moduleName = "qdomyoszwift"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/cagnulein/qdomyos-zwift/src/ios/BLEPeripheralManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "57"
endingLineNumber = "57"
offsetFromSymbolStart = "132">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
@@ -367,7 +335,7 @@
endingColumnNumber = "9223372036854775807"
startingLineNumber = "38"
endingLineNumber = "38"
landmarkName = "lockscreen::stepCadence()"
landmarkName = "lockscreen::virtualbike_setHeartRate(heartRate)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@@ -375,7 +343,7 @@
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "FE5697FF-F44C-43C2-A98D-C400EE56F047"
shouldBeEnabled = "No"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/ios/lockscreen.mm"
@@ -383,8 +351,8 @@
endingColumnNumber = "9223372036854775807"
startingLineNumber = "44"
endingLineNumber = "44"
landmarkName = "unknown"
landmarkType = "0">
landmarkName = "lockscreen::virtualbike_setCadence(crankRevolutions, lastCrankEventTime)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
@@ -399,7 +367,7 @@
endingColumnNumber = "9223372036854775807"
startingLineNumber = "37"
endingLineNumber = "37"
landmarkName = "lockscreen::stepCadence()"
landmarkName = "lockscreen::virtualbike_setHeartRate(heartRate)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@@ -407,7 +375,7 @@
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "3DBE0495-050A-4979-85D4-28B78676F212"
shouldBeEnabled = "No"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "../src/ios/lockscreen.mm"
@@ -415,7 +383,7 @@
endingColumnNumber = "9223372036854775807"
startingLineNumber = "43"
endingLineNumber = "43"
landmarkName = "lockscreen::setKcal(kcal)"
landmarkName = "lockscreen::virtualbike_setCadence(crankRevolutions, lastCrankEventTime)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@@ -431,7 +399,7 @@
endingColumnNumber = "9223372036854775807"
startingLineNumber = "32"
endingLineNumber = "32"
landmarkName = "lockscreen::heartRate()"
landmarkName = "lockscreen::virtualbike_ios()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@@ -463,7 +431,7 @@
endingColumnNumber = "9223372036854775807"
startingLineNumber = "35"
endingLineNumber = "35"
offsetFromSymbolStart = "32">
offsetFromSymbolStart = "22">
</Location>
<Location
uuid = "18F27065-9FB2-44A2-99D0-7D41061141A3 - 4daffae51fb2d733"
@@ -478,7 +446,7 @@
endingColumnNumber = "9223372036854775807"
startingLineNumber = "35"
endingLineNumber = "35"
offsetFromSymbolStart = "36">
offsetFromSymbolStart = "28">
</Location>
</Locations>
</BreakpointContent>

View File

@@ -1,62 +0,0 @@
{
"identifier" : "2816EB89",
"nonRenewingSubscriptions" : [
],
"products" : [
],
"settings" : {
},
"subscriptionGroups" : [
{
"id" : "F012E388",
"localizations" : [
],
"name" : "Swag Bag",
"subscriptions" : [
{
"adHocOffers" : [
],
"codeOffers" : [
],
"displayPrice" : "1.99",
"familyShareable" : false,
"groupNumber" : 1,
"internalID" : "F108BD35",
"introductoryOffer" : null,
"localizations" : [
{
"description" : "Swag Bag",
"displayName" : "Swag Bag",
"locale" : "en_US"
},
{
"description" : "Swag Bag",
"displayName" : "Swag Bag",
"locale" : "en_GB"
},
{
"description" : "Swag Bag",
"displayName" : "Swag Bag",
"locale" : "it"
}
],
"productID" : "org.cagnulein.qdomyoszwift.swagbag",
"recurringSubscriptionPeriod" : "P1M",
"referenceName" : "SwagBag",
"subscriptionGroupID" : "F012E388",
"type" : "RecurringSubscription"
}
]
}
],
"version" : {
"major" : 1,
"minor" : 2
}
}

View File

@@ -1,25 +1,21 @@
{
"images" : [
{
"filename" : "circular38mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : "<=145"
},
{
"filename" : "circular40mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">161"
},
{
"filename" : "circular42mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">145"
},
{
"filename" : "circular44mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"

View File

@@ -1,25 +1,21 @@
{
"images" : [
{
"filename" : "extra-large38mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : "<=145"
},
{
"filename" : "extra-large40mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">161"
},
{
"filename" : "extra-large42mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">145"
},
{
"filename" : "extra-large44mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"

View File

@@ -1,13 +1,11 @@
{
"images" : [
{
"filename" : "graphic-bezel40mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">161"
},
{
"filename" : "graphic-bezel44mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"

View File

@@ -1,13 +1,11 @@
{
"images" : [
{
"filename" : "graphic-circular40mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">161"
},
{
"filename" : "graphic-circular44mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"

View File

@@ -1,13 +1,11 @@
{
"images" : [
{
"filename" : "graphic-corner40mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">161"
},
{
"filename" : "graphic-corner44mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"

View File

@@ -1,25 +1,21 @@
{
"images" : [
{
"filename" : "graphic-extra-large38mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : "<=145"
},
{
"filename" : "graphic-extra-large40mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">161"
},
{
"filename" : "graphic-extra-large42mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">145"
},
{
"filename" : "graphic-extra-large44mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"

View File

@@ -1,13 +1,11 @@
{
"images" : [
{
"filename" : "graphic-large-rectangular40mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">161"
},
{
"filename" : "graphic-large-rectangular44mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"

View File

@@ -1,25 +1,21 @@
{
"images" : [
{
"filename" : "modular38mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : "<=145"
},
{
"filename" : "modular40mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">161"
},
{
"filename" : "modular42mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">145"
},
{
"filename" : "modular44mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"

View File

@@ -1,25 +1,21 @@
{
"images" : [
{
"filename" : "utility38mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : "<=145"
},
{
"filename" : "utility40mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">161"
},
{
"filename" : "utility42mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">145"
},
{
"filename" : "utility44mm@2x.png",
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"

View File

@@ -13,59 +13,6 @@ class ComplicationController: NSObject, CLKComplicationDataSource {
// MARK: - Timeline Configuration
private func templateForComplication(complication: CLKComplication) -> CLKComplicationTemplate? {
// Init default output:
var template: CLKComplicationTemplate? = nil
// Graphic Complications are only availably since watchOS 5.0:
if #available(watchOSApplicationExtension 5.0, *) {
// NOTE: Watch faces that support graphic templates are available only on Apple Watch Series 4 or later. So the binary on older devices (e.g. Watch Series 3) will not contain the images.
if complication.family == .graphicCircular {
let imageTemplate = CLKComplicationTemplateGraphicCircularImage()
// Check if asset exists, to prevent crash on non-supported devices:
if let fullColorImage = UIImage(named: "Complication/Graphic Circular") {
let imageProvider = CLKFullColorImageProvider.init(fullColorImage: fullColorImage)
imageTemplate.imageProvider = imageProvider
template = imageTemplate
}
}
else if complication.family == .graphicCorner {
let imageTemplate = CLKComplicationTemplateGraphicCornerCircularImage()
// Check if asset exists, to prevent crash on non-supported devices:
if let fullColorImage = UIImage(named: "Complication/Graphic Corner") {
let imageProvider = CLKFullColorImageProvider.init(fullColorImage: fullColorImage)
imageTemplate.imageProvider = imageProvider
template = imageTemplate
}
}
}
// For all watchOS versions:
if complication.family == .circularSmall {
let imageTemplate = CLKComplicationTemplateCircularSmallSimpleImage()
let imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Circular")!)
imageProvider.tintColor = UIColor.blue
imageTemplate.imageProvider = imageProvider
template = imageTemplate
}
else if complication.family == .modularSmall {
let imageTemplate = CLKComplicationTemplateModularSmallSimpleImage()
let imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Modular")!)
imageProvider.tintColor = UIColor.blue
imageTemplate.imageProvider = imageProvider
template = imageTemplate
}
else if complication.family == .utilitarianSmall {
let imageTemplate = CLKComplicationTemplateUtilitarianSmallSquare()
let imageProvider = CLKImageProvider(onePieceImage: UIImage(named: "Complication/Utilitarian")!)
imageProvider.tintColor = UIColor.blue
imageTemplate.imageProvider = imageProvider
template = imageTemplate
}
return template
}
func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) {
handler([.forward, .backward])
}
@@ -86,9 +33,7 @@ class ComplicationController: NSObject, CLKComplicationDataSource {
func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
// Call the handler with the current timeline entry
let template = templateForComplication(complication: complication)
let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template!)
handler(timelineEntry)
handler(nil)
}
func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) {
@@ -101,15 +46,11 @@ class ComplicationController: NSObject, CLKComplicationDataSource {
handler(nil)
}
func getPlaceholderTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
// This method will be called once per supported complication, and the results will be cached
handler(templateForComplication(complication: complication))
}
// MARK: - Placeholder Templates
func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) {
// This method will be called once per supported complication, and the results will be cached
handler(templateForComplication(complication: complication))
handler(nil)
}
}

View File

@@ -8,8 +8,6 @@
<string>watchkit Extension</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>NSMotionUsageDescription</key>
<string>access to step cadence in order to show it in the application</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
@@ -24,21 +22,6 @@
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>CLKComplicationPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ComplicationController</string>
<key>CLKComplicationSupportedFamilies</key>
<array>
<string>CLKComplicationFamilyModularSmall</string>
<string>CLKComplicationFamilyModularLarge</string>
<string>CLKComplicationFamilyUtilitarianSmall</string>
<string>CLKComplicationFamilyUtilitarianSmallFlat</string>
<string>CLKComplicationFamilyUtilitarianLarge</string>
<string>CLKComplicationFamilyCircularSmall</string>
<string>CLKComplicationFamilyExtraLarge</string>
<string>CLKComplicationFamilyGraphicCorner</string>
<string>CLKComplicationFamilyGraphicBezel</string>
<string>CLKComplicationFamilyGraphicCircular</string>
<string>CLKComplicationFamilyGraphicRectangular</string>
<string>CLKComplicationFamilyGraphicExtraLarge</string>
</array>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>

View File

@@ -8,17 +8,13 @@
import WatchKit
import HealthKit
import CoreMotion
class MainController: WKInterfaceController {
@IBOutlet weak var userNameLabel: WKInterfaceLabel!
@IBOutlet weak var stepCountsLabel: WKInterfaceLabel!
@IBOutlet weak var caloriesLabel: WKInterfaceLabel!
@IBOutlet weak var distanceLabel: WKInterfaceLabel!
@IBOutlet weak var heartRateLabel: WKInterfaceLabel!
@IBOutlet weak var startButton: WKInterfaceButton!
static var start: Bool! = false
let pedometer = CMPedometer()
override func awake(withContext context: Any?) {
super.awake(withContext: context)
@@ -32,15 +28,6 @@ class MainController: WKInterfaceController {
super.willActivate()
print("WILL ACTIVE")
WorkoutTracking.shared.fetchStepCounts()
if CMPedometer.isStepCountingAvailable() {
pedometer.startUpdates(from: Date()) { pedometerData, error in
guard let pedometerData = pedometerData, error == nil else { return }
self.stepCountsLabel.setText("\(Int(((pedometerData.currentCadence?.doubleValue ?? 0) * 60.0 / 2.0))) STEP CAD.")
WatchKitConnection.stepCadence = Int(((pedometerData.currentCadence?.doubleValue ?? 0) * 60.0 / 2.0))
WatchKitConnection.shared.sendMessage(message: ["stepCadence":
"\(WatchKitConnection.stepCadence)" as AnyObject])
}
}
}
override func didDeactivate() {
@@ -72,7 +59,6 @@ extension MainController {
}
extension MainController: WorkoutTrackingDelegate {
func didReceiveHealthKitDistanceCycling(_ distanceCycling: Double) {
}
@@ -86,17 +72,10 @@ extension MainController: WorkoutTrackingDelegate {
"\(heartRate)" as AnyObject])
WorkoutTracking.distance = WatchKitConnection.distance
WorkoutTracking.kcal = WatchKitConnection.kcal
self.distanceLabel.setText("Distance \(Double(WorkoutTracking.distance))")
self.caloriesLabel.setText("KCal \(Int(WorkoutTracking.kcal))")
//WorkoutTracking.cadenceSteps = pedometer.
}
func didReceiveHealthKitStepCounts(_ stepCounts: Double) {
//stepCountsLabel.setText("\(stepCounts) STEPS")
}
func didReceiveHealthKitStepCadence(_ stepCadence: Double) {
stepCountsLabel.setText("\(stepCounts) STEPS")
}
}

View File

@@ -23,7 +23,6 @@ class WatchKitConnection: NSObject {
static let shared = WatchKitConnection()
public static var distance = 0.0
public static var kcal = 0.0
public static var stepCadence = 0
weak var delegate: WatchKitConnectionDelegate?
private override init() {

View File

@@ -12,7 +12,6 @@ import HealthKit
protocol WorkoutTrackingDelegate: class {
func didReceiveHealthKitHeartRate(_ heartRate: Double)
func didReceiveHealthKitStepCounts(_ stepCounts: Double)
func didReceiveHealthKitStepCadence(_ stepCadence: Double)
func didReceiveHealthKitDistanceCycling(_ distanceCycling: Double)
func didReceiveHealthKitActiveEnergyBurned(_ activeEnergyBurned: Double)
}
@@ -28,9 +27,6 @@ class WorkoutTracking: NSObject {
static let shared = WorkoutTracking()
public static var distance = Double()
public static var kcal = Double()
public static var cadenceTimeStamp = NSDate().timeIntervalSince1970
public static var cadenceLastSteps = Double()
public static var cadenceSteps = 0
let healthStore = HKHealthStore()
let configuration = HKWorkoutConfiguration()
var workoutSession: HKWorkoutSession!
@@ -83,13 +79,7 @@ extension WorkoutTracking {
if let sum = result.sumQuantity() {
resultCount = sum.doubleValue(for: HKUnit.count())
let now = NSDate().timeIntervalSince1970
let deltaT = now - WorkoutTracking.cadenceTimeStamp
let deltaC = resultCount - WorkoutTracking.cadenceLastSteps
WorkoutTracking.cadenceLastSteps = resultCount
WorkoutTracking.cadenceTimeStamp = now
weakSelf.delegate?.didReceiveHealthKitStepCounts(resultCount)
weakSelf.delegate?.didReceiveHealthKitStepCadence((deltaC / deltaT) * 60)
} else {
print("Failed to fetch steps rate 2")
}
@@ -205,7 +195,6 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
workoutBuilder.endCollection(withEnd: Date()) { (success, error) in
}
workoutBuilder.finishWorkout{ (success, error) in }
}
func fetchStepCounts() {

View File

@@ -26,13 +26,6 @@
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "watch",
"role" : "notificationCenter",
"scale" : "2x",
"size" : "33x33",
"subtype" : "45mm"
},
{
"idiom" : "watch",
"role" : "appLauncher",
@@ -47,13 +40,6 @@
"size" : "44x44",
"subtype" : "40mm"
},
{
"idiom" : "watch",
"role" : "appLauncher",
"scale" : "2x",
"size" : "46x46",
"subtype" : "41mm"
},
{
"idiom" : "watch",
"role" : "appLauncher",
@@ -61,13 +47,6 @@
"size" : "50x50",
"subtype" : "44mm"
},
{
"idiom" : "watch",
"role" : "appLauncher",
"scale" : "2x",
"size" : "51x51",
"subtype" : "45mm"
},
{
"idiom" : "watch",
"role" : "quickLook",
@@ -89,13 +68,6 @@
"size" : "108x108",
"subtype" : "44mm"
},
{
"idiom" : "watch",
"role" : "quickLook",
"scale" : "2x",
"size" : "117x117",
"subtype" : "45mm"
},
{
"idiom" : "watch-marketing",
"scale" : "1x",

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -103,7 +103,7 @@
"size" : "83.5x83.5"
},
{
"filename" : "ItunesArtwork-1.png",
"filename" : "iTunesArtwork@2x.png",
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
@@ -138,13 +138,6 @@
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "watch",
"role" : "notificationCenter",
"scale" : "2x",
"size" : "33x33",
"subtype" : "45mm"
},
{
"filename" : "80x80-1.png",
"idiom" : "watch",
@@ -161,13 +154,6 @@
"size" : "44x44",
"subtype" : "40mm"
},
{
"idiom" : "watch",
"role" : "appLauncher",
"scale" : "2x",
"size" : "46x46",
"subtype" : "41mm"
},
{
"filename" : "50@2x-1.png",
"idiom" : "watch",
@@ -176,13 +162,6 @@
"size" : "50x50",
"subtype" : "44mm"
},
{
"idiom" : "watch",
"role" : "appLauncher",
"scale" : "2x",
"size" : "51x51",
"subtype" : "45mm"
},
{
"filename" : "86@2x-1.png",
"idiom" : "watch",
@@ -207,13 +186,6 @@
"size" : "108x108",
"subtype" : "44mm"
},
{
"idiom" : "watch",
"role" : "quickLook",
"scale" : "2x",
"size" : "117x117",
"subtype" : "45mm"
},
{
"filename" : "1024@1x.png",
"idiom" : "watch-marketing",

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="19529" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Tpn-rd-UUX">
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="17506" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Tpn-rd-UUX">
<device id="watch38"/>
<dependencies>
<deployment identifier="watchOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="19514"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="17500"/>
</dependencies>
<scenes>
<!--Main-->
@@ -12,20 +12,16 @@
<objects>
<controller identifier="Main" hidesWhenLoading="NO" id="Tpn-rd-UUX" customClass="MainController" customModule="watchkit_Extension">
<items>
<label width="136" alignment="left" text="QZ Fitness" textAlignment="center" id="SlU-M7-WGB"/>
<label width="136" alignment="left" text="qdomyos-zwift" textAlignment="center" id="SlU-M7-WGB"/>
<label width="136" alignment="left" text="Heart Rate" id="Nda-m1-XRw"/>
<label width="136" alignment="left" text="Step Counts" id="HpA-e9-6YV"/>
<button width="1" alignment="left" title="Start" id="vZg-X8-uY5">
<connections>
<action selector="startWorkout" destination="Tpn-rd-UUX" id="UaW-pR-tn6"/>
</connections>
</button>
<label width="136" alignment="left" text="Heart Rate" id="Nda-m1-XRw"/>
<label width="136" alignment="left" text="Step Counts" id="HpA-e9-6YV"/>
<label width="136" alignment="left" text="Calories" id="Szi-Jp-J3S"/>
<label width="136" alignment="left" text="Distance" id="eRf-NJ-6If"/>
</items>
<connections>
<outlet property="caloriesLabel" destination="Szi-Jp-J3S" id="trd-YS-bJy"/>
<outlet property="distanceLabel" destination="eRf-NJ-6If" id="ZE2-OB-jqN"/>
<outlet property="heartRateLabel" destination="Nda-m1-XRw" id="1la-8R-3jG"/>
<outlet property="startButton" destination="vZg-X8-uY5" id="pJc-09-kfV"/>
<outlet property="stepCountsLabel" destination="HpA-e9-6YV" id="Z88-ej-6oG"/>

View File

@@ -1,24 +1,10 @@
FROM ubuntu:latest
FROM debian:stable
MAINTAINER cagnulein
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Moscow
ENV MAKEFLAGS -j8
WORKDIR /usr/local/src
RUN apt-get update && apt-get install -y tzdata
# utils
RUN apt -y update
RUN apt -y upgrade
RUN apt update -y && apt-get install -y git qt5-default libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-default libqt5networkauth5-dev libqt5websockets5* libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev libxcb-shape0-dev libxcb-xkb-dev build-essential
RUN git clone https://github.com/cagnulein/qdomyos-zwift.git
WORKDIR /usr/local/src/qdomyos-zwift
RUN git submodule update --init src/smtpclient/
RUN git submodule update --init src/qmdnsengine/
WORKDIR /usr/local/src/qdomyos-zwift/src
RUN qmake
RUN make -j4
WORKDIR /usr/local/src/qdomyos-zwift/src
CMD ["./qdomyos-zwift","-no-gui"]
RUN apt -y install git libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-default

View File

@@ -8,11 +8,9 @@ Once you've installed QDomyos-Zwift, you can access the [operation guide](30_usa
```buildoutcfg
$ sudo apt update && sudo apt upgrade # this is very important on raspberry pi: you need the bluetooth firmware updated!
$ sudo apt install git qtquickcontrols2-5-dev libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-assistant libqt5networkauth5-dev libqt5websockets5-dev qml-module* libqt5texttospeech5-dev libqt5texttospeech5 libqt5location5-plugins qtlocation5-dev qtmultimedia5-dev libqt5multimediawidgets5 libqt5multimedia5-plugins libqt5multimedia5
$ sudo apt install git libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-default libqt5networkauth5-dev
$ git clone https://github.com/cagnulein/qdomyos-zwift.git
$ cd qdomyos-zwift
$ git submodule update --init src/smtpclient/
$ git submodule update --init src/qmdnsengine/
$ cd src
$ qmake
$ make -j4
@@ -102,14 +100,13 @@ This operation takes a moment to complete.
#### Install qdomyos-zwift from sources
`sudo apt install git libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-assistant libqt5networkauth5-dev libqt5websockets5-dev qtmultimedia5-dev libqt5multimediawidgets5 libqt5multimedia5-plugins libqt5multimedia5 qtlocation5-dev qtquickcontrols2-5-dev libqt5texttospeech5-dev libqt5texttospeech5`
`sudo apt install git libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-default libqt5networkauth5-dev`
`git clone https://github.com/cagnulein/qdomyos-zwift.git`
`cd qdomyos-zwift`
`git submodule update --init src/smtpclient/`
`git submodule update --init src/qmdnsengine/`
`cd src`
`qmake`
`git submodule update --init src/smtpclient/`
`cd src`
`qmake`
`make`
Please note :

View File

@@ -11,12 +11,26 @@ This list is not exhaustive. Please report any application known to be working w
|[Fulgaz](21_applications_detail.md#fulgaz)|![bike](img/20_bike.png)|![IOS](img/20_apple.png) ![Android](img/20_android.png) ![PC](img/20_windows.png)|Yes|Yes|Yes|Yes, no FTMS support (see note)|Yes (see note) |
# Supported devices
Check the full list https://github.com/cagnulein/qdomyos-zwift/wiki/Equipment-Compatibility
This list is not exhaustive.
Try the qdomyos app with your fitness appliance and report how it is going.
If it's not working, you can [ask for your device to be supported](#ask-for-device-support)
## Supported bikes
|Manufacturer|Model|Speed|RPM|Power|HRM|Resistence Control|
|------------|-----|------------|---|-----|---|------------------|
|[Echelon](22_devices_detail.md#echelon)|Connect Sport|Yes|Yes|Yes|Yes|N/A|
|[Sportstech](22_devices_detail.md#sportstech)|ESX500|Yes|Yes|Yes|Yes|Yes|
## Supported treadmills
|Manufacturer|Model|Speed|HRM|Inclinaison Control| Speed control|
|------------|-----|------------|---|-------------------|--------------|
|Domyos|Intense Run|Yes|Yes|Yes|Yes|
|Domyos|T900c|Yes|Yes|Yes|Yes|
|Toorx|TRX Route Key|Yes|Yes|Yes|Yes|
# Ask for device support
You can ask for supporting a device by opening an issue and following these steps.

View File

@@ -21,33 +21,32 @@ Please refer to this article for more information under [QML Operations](https:/
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** |
|:------------------------------|:---------|:------------|:-----------------------------------------------------------------------------|
| -no-gui | Boolean | False | Disable GUI |
| -qml | Boolean | False | Enables the QML interface |
| -miles | Boolean | False | Swithes to Imperial Units System |
| -no-console | Boolean | False | Not in use |
| -test-resistance | Boolean | False | |
| -no-log | Boolean | False | Disable Logging |
| -no-write-resistance | Boolean | False | Disable resistance instructions from QZ to your fitness equipment |
| -no-heart-service | Boolean | False | Do not simulate external HR monitor, use only FTMS |
| -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 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 | |
| -service-changed | Boolean | False | |
| -bike-wheel-revs | Boolean | False | |
| -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 finding your fitness equipment) |
| -poll-device-time | Int | 200 (ms) | Frequency to refresh informations 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 |
| **Option** | **Type** | **Default** | **Function** |
|:------------------------|:---------|:------------|:-----------------------------------------------------------------------------|
| -no-gui | Boolean | False | Disable GUI |
| -qml | Boolean | False | Enables the QML interface |
| -miles | Boolean | False | Swithes to Imperial Units System |
| -no-console | Boolean | False | Not in use |
| -test-resistance | Boolean | False | |
| -no-log | Boolean | False | Disable Logging |
| -no-write-resistance | Boolean | False | Disable resistance instructions from QZ to your fitness equipment |
| -no-heart-service | Boolean | False | Do not simulate external HR monitor, use only FTMS |
| -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 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 | |
| -service-changed | Boolean | False | |
| -bike-wheel-revs | Boolean | False | |
| -run-cadence-sensor | Boolean | False | |
| -train | String | | Force training program |
| -name | String | | Force bluetooth device name (if QZ struggles finding your fitness equipment) |
| -poll-device-time | Int | 200 (ms) | Frequency to refresh informations 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,365 +0,0 @@
# QDomyos-Zwift WebSocket API Installation & Operation guide
# Installation
## About
The QDomyos-Zwift WebSocket API can be installed from source on Linux, Raspberry Pi (4, 3, zero W), macOS, Android and IOS.
However, this guide will only focus on the Linux (Debian 11) Installation and Raspberry Pi cause there are the most useful case in headless control.
If you already install the Web Socket, feel free to [skip to the Usage section](#usage).
## Requirement
To Install QDomyos-Zwift with WebSocket API you will need Qt 5.12.2+ and the following modules :
- Qt Bluetooth
- Qt Widgets
- Qt Positioning
- Qt XML
- Qt Charts
- Qt Network
- Qt Network Authorization
- Qt WebSockets
- Qt Assistant
Unfortunately under Debian 11 (or Raspbian 11) the Qt 5 packages are not recent enough for compilation however this guide will explain how to manually compile the latest version of Qt (5.12.12)
If you already had Qt 5.12.2 or more, feel free to [skip to Install Qt Httpserver](#install-qt-httpserver).
## Install Qt 5.12.2
*If you compile for a Raspberry Pi Zero, it's* ***faster and easy*** *to do all the Raspberry Pi task on a Raspberry Pi 4 and after copy compiled binary files toe the Raspberry Pi Zero*
For more info on the steps [please refer to the source](#source)
Before do anything. Make sure all your packages are updated :
```bash
apt update && apt upgrade # this is very important on raspberry pi: you need the bluetooth firmware updated!
```
After download last version of Qt Source and extract them :
```bash
wget https://download.qt.io/official_releases/qt/5.12/5.12.12/single/qt-everywhere-src-5.12.12.tar.xz
```
If you compile for a Raspberry Pi you will need the Raspberry Pi Qt Configuration for raspberry pi and install it in the source :
```bash
git clone https://github.com/oniongarlic/qt-raspberrypi-configuration.git
cd qt-raspberrypi-configuration && make install DESTDIR=../qt-everywhere-src-5.12.12
```
Install the bare minimum required development packages for building Qt 5 with apt :
```bash
apt install build-essential libfontconfig1-dev libdbus-1-dev libfreetype6-dev libicu-dev libinput-dev libxkbcommon-dev libsqlite3-dev libssl-dev libpng-dev libjpeg-dev libglib2.0-dev libraspberrypi-dev
```
*For raspberry Pi install `libraspberrypi-dev` package* :
```bash
apt install libraspberrypi-dev
```
Now install all required development packages for building all Qt 5 modules:
```bash
apt install bluez libgbm-dev
apt install libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xinerama0 gdbserver
apt install libegl1-mesa libegl1-mesa-dev libgles2-mesa libgles2-mesa-dev
apt install wiringpi libnfc-bin libnfc-dev fonts-texgyre libts-dev
apt install libbluetooth-dev bluez-tools gstreamer1.0-plugins* libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libopenal-data libopenal1 libopenal-dev pulseaudio
apt install libgstreamer*-dev
apt install gstreamer*-dev
apt install libasound2-dev libavcodec-dev libavformat-dev libswscale-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev gstreamer-tools libgstreamer-plugins-*
apt install qtdeclarative5-dev
apt install libvlc-dev
```
On Raspbian Stretch/Buster/Bullseye the OpenGL library files have been renamed so that they wouldn't conflict with Mesa installed ones. Unfortunately Qt configure script is still looking for the old names.
So ***on your target Raspberry Pi*** you need to symlink those file to make sure Qt run correctly.
```bash
ln -s /usr/lib/arm-linux-gnueabihf/libGLESv2.so /usr/lib/libbrcmGLESv2.so
ln -s /usr/lib/arm-linux-gnueabihf/libEGL.so /usr/lib/libbrcmEGL.so
```
Now all dependency are installed. It's time to create build folder and compiled.
```bash
mkdir build
cd build
# For Raspberry Pi Zero or 3
PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig ../qt-everywhere-src-5.12.12/configure -platform linux-rpi-g++ -v -opengl es2 -eglfs -no-gtk -opensource -confirm-license -release -reduce-exports -force-pkg-config -nomake examples -no-compile-examples -skip qtwayland -skip qtwebengine -no-feature-geoservices_mapboxgl -qt-pcre -no-pch -ssl -evdev -system-freetype -fontconfig -glib -prefix /opt/Qt/5.12.12 -qpa eglfs
CFLAGS="-march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp" make -j3 # Remove -j3 if you compiled directly on Raspberry Pi Zero
# For Raspberry Pi 4
PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/share/pkgconfig ../qt-everywhere-src-5.12.12/configure -platform linux-rpi4-v3d-g++ -v -opengl es2 -eglfs -no-gtk -opensource -confirm-license -release -reduce-exports -force-pkg-config -nomake examples -no-compile-examples -skip qtwayland -skip qtwebengine -no-feature-geoservices_mapboxgl -qt-pcre -no-pch -ssl -evdev -system-freetype -fontconfig -glib -prefix /opt/Qt/5.12.12 -qpa eglfs
CFLAGS="-march=armv8-a -mtune=cortex-a72 -mfpu=crypto-neon-fp-armv8" make -j3
# For Debian 11 x64 (Not tested)
../qt-everywhere-src-5.12.12/configure -v -opengl es2 -eglfs -no-gtk -opensource -confirm-license -release -reduce-exports -force-pkg-config -nomake examples -no-compile-examples -skip qtwayland -skip qtwebengine -no-feature-geoservices_mapboxgl -qt-pcre -no-pch -ssl -evdev -system-freetype -fontconfig -glib -prefix /opt/Qt/5.12.12 -qpa eglfs
make
```
Finally, if you cross compiled you can transfer the build folder to other machine and then just run as root in the build folder :
```bash
make install
```
# Install Qt Httpserver
Like explain in PR #252, to make work the Http Server you will need to manually compile `qthttpserver` module.
For that just run following commands in your home directory :
```bash
cd ~
git clone https://github.com/qt-labs/qthttpserver
cd ~/qthttpserver/src/3rdparty/http-parser
wget https://raw.githubusercontent.com/nodejs/http-parser/main/http_parser.h
wget https://raw.githubusercontent.com/nodejs/http-parser/main/http_parser.c
cd ~/qthttpserver/src
qmake # Please note if you compiled Qt you need to specify /opt/Qt/5.12.12/bin/qmake
make
# Wait...
sudo make install
```
***You have successfully installed Qt Httpserver***
# Install QDomyos-Zwift
If you already compile QDomyos-Zwift and you just compiled a new version of Qt.
Please delete the whole QDomyos-Zwift folder and restart from scratch to prevent linking issues.
```bash
cd ~
git clone https://github.com/cagnulein/qdomyos-zwift.git
cd ~/qdomyos-zwift
git submodule update --init ~/qdomyos-zwift/src/smtpclient/
cd ~/qdomyos-zwift/src
qmake # Please note if you compiled Qt you need to specify /opt/Qt/5.12.12/bin/qmake
make -j4 # Remove -j4 if you compiled on Raspberry Pi Zero
```
Now installed you need to compile like say in PR #252 and issue #572 template/debug in the same directory of source file of QDomyos-Zwift.
```bash
cp -r ~/qdomyos-zwift/src/templates/debug ~/qdomyos-zwift/src/.
cp -r ~/qdomyos-zwift/src/templates/debug/* ~/qdomyos-zwift/src/.
```
Last if you can't run QML version (probably because you don't had a X11 Server.) you need to manually edit the configuration file in `/root/.config/Roberto Viola/qDomyos-Zwift.conf` and add :
```
template_inner_QZWS_enabled=true
template_inner_QZWS_folders=:/inner_templates//chartjs
template_inner_QZWS_ips=192.168.1.42
template_inner_QZWS_port=34107
template_inner_QZWS_type=WebServer
```
In this config file we open an HTTP Server on port 34107 with bind to 192.168.1.42 but feel free to change these values.
Finally, ***do not move `qdomyos-zwift` from src folder*** and run it as Root
# Usage
The way that [WebSocket](https://developer.mozilla.org/docs/Web/API/WebSockets_API) work in QDomyos-Zwift is by sending commands and listen events.
## Workout Event
The workout Event is the default message send almost every second by QDomyos-Zwift to inform you which state is your equipment.
Here what is look like :
```json
{
"BIKE_TYPE": 2,
"ELLIPTICAL_TYPE": 4,
"ROWING_TYPE": 3,
"TREADMILL_TYPE": 1,
"UNKNOWN_TYPE": 0,
"deviceId": "0B:54:49:D1:BC:DA",
"deviceName": "Domyos-TC-0314",
"deviceRSSI": 0,
"deviceType": 1,
"deviceConnected": false,
"devicePaused": false,
"elapsed_s": 0,
"elapsed_m": 0,
"elapsed_h": 0,
"pace_s": 0,
"pace_m": 0,
"pace_h": 0,
"moving_s": 0,
"moving_m": 0,
"moving_h": 0,
"speed": 0,
"speed_avg": 0,
"calories": 0,
"distance": 0,
"heart": 0,
"heart_avg": 0,
"heart_max": 0,
"jouls": 0,
"elevation": 0,
"difficult": 1,
"watts": 0,
"watts_avg": 0,
"watts_max": 0,
"kgwatts": 0,
"kgwatts_avg": 0,
"kgwatts_max": 0,
"workoutName": "",
"workoutStartDate": "",
"instructorName": "",
"latitude": null,
"longitude": null,
"nickName": "N/A",
"inclination": 0,
"inclination_avg": 0
}
```
## Commands
To send commands you will need to send a socket message in JSON format like :
```json
{
"msg": "pause"
}
```
which `msg` is always the name of the command. Command also return on WebSocket message like to acknowledge command :
```json
{
"msg": "R_pause"
}
```
Here is a list of the most "useful" commands
### Start
#### Description :
Allows you to start the bike / treadmill (Reset Timer if bike / treadmill is stopped)
#### Send :
```json
{
"msg": "start"
}
```
#### Response :
```json
{
"msg": "R_start"
}
```
### Pause
#### Description :
Allows you to stop (pause) the bike / treadmill without reset timer.
#### Send :
```json
{
"msg": "pause"
}
```
#### Response :
```json
{
"msg": "R_pause"
}
```
### Stop
#### Description :
Allows you to stop the bike / treadmill and reset timer.
#### Send :
```json
{
"msg": "stop"
}
```
#### Response :
```json
{
"msg": "R_stop"
}
```
### SetSpeed
#### Description :
Allows you to control the treadmill speed.
#### Send :
```json
{
"msg": "setspeed",
"content": {
"value": 8.0
}
}
```
#### Response :
```json
{
"msg": "R_setspeed",
"content": {
"value": 8.0
}
}
```
### SetResistance
#### Description :
Allows you to control the resistance bike or the treadmill incline.
#### Send :
```json
{
"msg": "setresistance",
"content": {
"value": 8.0
}
}
```
#### Response :
```json
{
"msg": "R_setresistance",
"content": {
"value": 8.0
}
}
```
### SetFanSpeed
#### Description :
Allows you to control the fan bike / treadmill speed.
#### Send :
```json
{
"msg": "setfanspeed",
"content": {
"value": 8.0
}
}
```
#### Response :
```json
{
"msg": "R_setfanspeed",
"content": {
"value": 8.0
}
}
```
# Source
How compile Qt 5.12.10 on Raspberry Pi : https://www.tal.org/tutorials/building-qt-512-raspberry-pi
How cross compile Qt 5.12.5 on Raspberry Pi (in French) : https://wiki.logre.eu/index.php/Cross-compilation_Qt_5.12.5_pour_Raspberry_Pi
Issue [REQ] Add to qdomyos an API for remote access to treadmill #572
PR "Templated" connections and Web server #252

View File

@@ -1,87 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--Copyright 2011 Bluetooth SIG, Inc. All rights reserved.-->
<Characteristic xsi:noNamespaceSchemaLocation="http://schemas.bluetooth.org/Documents/characteristic.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="RSC Measurement"
type="org.bluetooth.characteristic.rsc_measurement" uuid="2A53"
last-modified="2012-09-29" approved="Yes">
<InformativeText>
<Summary>The RSC Measurement characteristic (RSC refers to
Running Speed and Cadence) is a variable length structure
containing a Flags field, an Instantaneous Speed field and an
Instantaneous Cadence field and, based on the contents of the
Flags field, may contain a Stride Length field and a Total
Distance field.</Summary>
</InformativeText>
<Value>
<Field name="Flags">
<InformativeText>These flags define which data fields are
present in the Characteristic value.</InformativeText>
<Requirement>Mandatory</Requirement>
<Format>8bit</Format>
<BitField>
<Bit index="0" size="1"
name="Instantaneous Stride Length Present">
<Enumerations>
<Enumeration key="0" value="False" />
<Enumeration key="1" value="True" requires="C1" />
</Enumerations>
</Bit>
<Bit index="1" size="1" name="Total Distance Present">
<Enumerations>
<Enumeration key="0" value="False" />
<Enumeration key="1" value="True" requires="C2" />
</Enumerations>
</Bit>
<Bit index="2" size="1"
name="Walking or Running Status bits">
<Enumerations>
<Enumeration key="0" value="Walking" />
<Enumeration key="1" value="Running" />
</Enumerations>
</Bit>
<ReservedForFutureUse index="3" size="5" />
</BitField>
</Field>
<Field name="Instantaneous Speed">
<InformativeText>Unit is in m/s with a resolution of 1/256
s</InformativeText>
<Requirement>Mandatory</Requirement>
<Format>uint16</Format>
<Unit>org.bluetooth.unit.velocity.metres_per_second</Unit>
</Field>
<Field name="Instantaneous Cadence">
<InformativeText>Unit is in 1/minute (or RPM) with a
resolutions of 1 1/min (or 1 RPM)</InformativeText>
<Requirement>Mandatory</Requirement>
<Format>uint8</Format>
<Unit>
org.bluetooth.unit.angular_velocity.revolution_per_minute</Unit>
</Field>
<Field name="Instantaneous Stride Length">
<InformativeText>
<p>C1: Field exists if the key of bit 0 of the Flags field
is set to 1.</p>
<p>- Unit is in meter with a resolution of 1/100 m (or
centimeter).</p>
</InformativeText>
<Requirement>C1</Requirement>
<Format>uint16</Format>
<Unit>org.bluetooth.unit.length.meter</Unit>
</Field>
<Field name="Total Distance">
<InformativeText>
<p>C2: Field exists if the key of bit 1 of the Flags field
is set to 1.</p>
<p>- Unit is in meter with a resolution of 1/10 m (or
decimeter).</p>
</InformativeText>
<Requirement>C2</Requirement>
<Format>uint32</Format>
<Unit>org.bluetooth.unit.length.meter</Unit>
</Field>
</Value>
<Note>The fields in the above table are in the order of LSO to
MSO. Where LSO = Least Significant Octet and MSO = Most
Significant Octet.</Note>
</Characteristic>

View File

@@ -1,161 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2011 Bluetooth SIG, Inc. All rights reserved. -->
<Service xsi:noNamespaceSchemaLocation="http://schemas.bluetooth.org/Documents/service.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="Running Speed and Cadence"
type="org.bluetooth.service.running_speed_and_cadence" uuid="1814"
last-modified="2012-3-26" approved="Yes">
<InformativeText>
<Abstract>This service exposes speed, cadence and other data
from a Running Speed and Cadence Sensor intended for fitness
applications.</Abstract>
<Summary>The Running Speed and Cadence (RSC) Service exposes
speed, cadence and other data related to fitness applications
such as the stride length and the total distance the user has
traveled while using the Speed and Cadence Sensor
(Server).</Summary>
</InformativeText>
<Dependencies>
<Dependency>This service has no dependencies on other
GATT-based services.</Dependency>
</Dependencies>
<GATTRequirements>
<Requirement subProcedure="Write Characteristic Values">
C1</Requirement>
<Requirement subProcedure="Notifications">
Mandatory</Requirement>
<Requirement subProcedure="Indications">C1</Requirement>
<Requirement subProcedure="Read Characteristic Descriptors">
Mandatory</Requirement>
<Requirement subProcedure="Write Characteristic Descriptors">
Mandatory</Requirement>
</GATTRequirements>
<Note>C1: Mandatory if the SC Control Point characteristic is
supported, otherwise excluded for this service.</Note>
<Transports>
<Classic>true</Classic>
<LowEnergy>true</LowEnergy>
</Transports>
<ErrorCodes>
<ErrorCode name="Procedure Already in Progress" code="0x80">A
SC Control Point request cannot be serviced because a
previously triggered SC Control Point operation is still in
progress.</ErrorCode>
<ErrorCode name="Client Characteristic Configuration descriptor improperly configured"
code="0x81">The Client Characteristic Configuration descriptor
is not configured according to the requirements of the
service.</ErrorCode>
</ErrorCodes>
<Characteristics>
<Characteristic name="RSC Measurement"
type="org.bluetooth.characteristic.rsc_measurement">
<InformativeText>The RSC Measurement characteristic is used
to send speed and cadence measurements.</InformativeText>
<Requirement>Mandatory</Requirement>
<Properties>
<Read>Excluded</Read>
<Write>Excluded</Write>
<WriteWithoutResponse>Excluded</WriteWithoutResponse>
<SignedWrite>Excluded</SignedWrite>
<ReliableWrite>Excluded</ReliableWrite>
<Notify>Mandatory</Notify>
<Indicate>Excluded</Indicate>
<WritableAuxiliaries>Excluded</WritableAuxiliaries>
<Broadcast>Excluded</Broadcast>
</Properties>
<Descriptors>
<Descriptor name="Client Characteristic Configuration"
type="org.bluetooth.descriptor.gatt.client_characteristic_configuration">
<Requirement>Mandatory</Requirement>
<Properties>
<Read>Mandatory</Read>
<Write>Mandatory</Write>
</Properties>
</Descriptor>
</Descriptors>
</Characteristic>
<Characteristic name="RSC Feature"
type="org.bluetooth.characteristic.rsc_feature">
<InformativeText>The RSC Feature characteristic is used to
describe the supported features of the Server. Reserved for
Future Use (RFU) bits in the SC Feature characteristic value
are set to 0.</InformativeText>
<Requirement>Mandatory</Requirement>
<Properties>
<Read>Mandatory</Read>
<Write>Excluded</Write>
<WriteWithoutResponse>Excluded</WriteWithoutResponse>
<SignedWrite>Excluded</SignedWrite>
<ReliableWrite>Excluded</ReliableWrite>
<Notify>Excluded</Notify>
<Indicate>Excluded</Indicate>
<WritableAuxiliaries>Excluded</WritableAuxiliaries>
<Broadcast>Excluded</Broadcast>
</Properties>
</Characteristic>
<Characteristic name="Sensor Location"
type="org.bluetooth.characteristic.sensor_location">
<InformativeText>
<p>The Sensor Location characteristic of the device is used
to describe the physical location of the Server when
correctly fitted.</p>
<p>
<b>C1:</b>Mandatory if the Multiple Sensor Location feature
is supported, otherwise optional.</p>
</InformativeText>
<Requirement>C1</Requirement>
<Properties>
<Read>Mandatory</Read>
<Write>Excluded</Write>
<WriteWithoutResponse>Excluded</WriteWithoutResponse>
<SignedWrite>Excluded</SignedWrite>
<ReliableWrite>Excluded</ReliableWrite>
<Notify>Excluded</Notify>
<Indicate>Excluded</Indicate>
<WritableAuxiliaries>Excluded</WritableAuxiliaries>
<Broadcast>Excluded</Broadcast>
</Properties>
</Characteristic>
<Characteristic name="SC Control Point"
type="org.bluetooth.characteristic.sc_control_point">
<InformativeText>
<p>If the SC Control Point is supported, profiles utilizing
this service are required to ensure that the Client
configures the SC Control Point characteristic for
indications (i.e. via the Client Characteristic
Configuration descriptor) at the first connection.</p>
<p>Support for this characteristic is mandatory if the
Server supports Calibration Procedure, Total Distance or
Multiple Sensor Locations features, otherwise it is
excluded.</p>
<p>
<b>C2:</b>Mandatory if at least one SC Control Point
procedure is supported, otherwise excluded.</p>
</InformativeText>
<Requirement>C2</Requirement>
<Properties>
<Read>Excluded</Read>
<Write>Mandatory</Write>
<WriteWithoutResponse>Excluded</WriteWithoutResponse>
<SignedWrite>Excluded</SignedWrite>
<ReliableWrite>Excluded</ReliableWrite>
<Notify>Excluded</Notify>
<Indicate>Mandatory</Indicate>
<WritableAuxiliaries>Excluded</WritableAuxiliaries>
<Broadcast>Excluded</Broadcast>
</Properties>
<Descriptors>
<Descriptor name="Client Characteristic Configuration"
type="org.bluetooth.descriptor.gatt.client_characteristic_configuration">
<Requirement>if_characteristic_supported</Requirement>
<Properties>
<Read>Mandatory</Read>
<Write>Mandatory</Write>
</Properties>
</Descriptor>
</Descriptors>
</Characteristic>
</Characteristics>
</Service>

View File

@@ -1,6 +0,0 @@
copy icons\iOS\iTunesArtwork@2x.png build-qdomyos-zwift-Qt_5_15_2_for_UWP_64bit_MSVC_2019-Release\release
del build-qdomyos-zwift-Qt_5_15_2_for_UWP_64bit_MSVC_2019-Release\release\qz.appx
cd build-qdomyos-zwift-Qt_5_15_2_for_UWP_64bit_MSVC_2019-Release\release
"C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\makeappx.exe" pack /d . /p qz
explorer build-qdomyos-zwift-Qt_5_15_2_for_UWP_64bit_MSVC_2019-Release\release
pause

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

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