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
1443 changed files with 84520 additions and 395075 deletions

2
.github/FUNDING.yml vendored
View File

@@ -7,6 +7,6 @@ ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: cagnulein
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ['https://www.buymeacoffee.com/cagnulein'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

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 }}

File diff suppressed because it is too large Load Diff

17
.gitignore vendored
View File

@@ -18,14 +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/*
template-examples/youtube-viewer/node_modules/*
template-examples/youtube-viewer/*.json
template-examples/youtube-viewer/.eslintrc.js
@@ -38,15 +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
google_test/*
# Qt-es
*.pro.user
*build-*
!build-qdomyos-zwift-Qt_*_for_iOS-Debug # Needed for Apple Watch
src/inner_templates/googlemaps/cesium-key.js
*.autosave
.vscode/settings.json
/tst/Devices/.vs
src/inner_templates/googlemaps/cesium-key.js

18
.gitmodules vendored
View File

@@ -3,20 +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
[submodule "tst/googletest"]
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
[submodule "zwiftplay"]
path = zwiftplay
url = https://github.com/cagnulein/zwiftplay.git
branch = lib
url = https://github.com/bluetiger9/SmtpClient-for-Qt.git

16
.vscode/launch.json vendored
View File

@@ -1,16 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) Launch",
"type": "cppvsdbg",
"request": "launch",
"program": "C://Users//violarob//Downloads//windows-msvc2019-binary-no-python (1)//output/qdomyos-zwift.exe",
"symbolSearchPath": "C://Users//violarob//Downloads//windows-msvc2019-binary-no-python (1)//output/qdomyos-zwift.pdb",
"sourceFileMap": {
"d:/a/qdomyos-zwift/qdomyos-zwift": "c:/work/qdomyos-zwift/",
"compiled_source_path": "C://Users//violarob//Downloads//windows-msvc2019-binary-no-python (1)//output/"
}
}
]
}

View File

@@ -1,128 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
roberto.viola83@gmail.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@@ -1,437 +0,0 @@
/** NimBLE_Server Demo:
*
This is working to broadcast Power and Cadence under the Cycling Power Service Profile
Data tested against Edge and Phone
*
*/
#include <Arduino.h>
#include <NimBLEDevice.h>
short powerInstantaneous = 0;
short cadenceInstantaneous = 0;
short speedInstantaneous = 0;
float powerScale = 1.28; // incoming power is multiplied by this value for correction
short resistance = 0; //Not currently doing anything with this value after receiving it
bool notify = false;
// Define stuff for the Client that will receive data from Fitness Machine
// The remote service we wish to connect to.
static BLEUUID serviceUUID("1826"); // Fitness Machine
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("2ad2"); // Indoor Bike (Fitness Machine)
static BLEUUID HRserviceUUID("180D"); // HR Service
static BLEUUID HRcharUUID("2a37"); // HR Measuremente
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic *pRemoteCharacteristic;
static BLEAdvertisedDevice *myDevice;
/*
* Server Stuff
*/
static NimBLEServer *pServer;
/** None of these are required as they will be handled by the library with defaults. **
** Remove as you see fit for your needs */
class ServerCallbacks : public NimBLEServerCallbacks
{
void onConnect(NimBLEServer *pServer)
{
Serial.println("Client connected");
Serial.println("Multi-connect support: start advertising");
NimBLEDevice::startAdvertising();
};
/** Alternative onConnect() method to extract details of the connection.
* See: src/ble_gap.h for the details of the ble_gap_conn_desc struct.
*/
void onConnect(NimBLEServer *pServer, ble_gap_conn_desc *desc)
{
Serial.print("Client address: ");
Serial.println(NimBLEAddress(desc->peer_ota_addr).toString().c_str());
/** We can use the connection handle here to ask for different connection parameters.
* Args: connection handle, min connection interval, max connection interval
* latency, supervision timeout.
* Units; Min/Max Intervals: 1.25 millisecond increments.
* Latency: number of intervals allowed to skip.
* Timeout: 10 millisecond increments, try for 5x interval time for best results.
*/
pServer->updateConnParams(desc->conn_handle, 24, 48, 0, 60);
};
void onDisconnect(NimBLEServer *pServer)
{
Serial.println("Client disconnected - start advertising");
NimBLEDevice::startAdvertising();
};
void onMTUChange(uint16_t MTU, ble_gap_conn_desc *desc)
{
Serial.printf("MTU updated: %u for connection ID: %u\n", MTU, desc->conn_handle);
};
};
/** Handler class for characteristic actions */
class CharacteristicCallbacks : public NimBLECharacteristicCallbacks
{
void onRead(NimBLECharacteristic *pCharacteristic)
{
Serial.print(pCharacteristic->getUUID().toString().c_str());
Serial.print(": onRead(), value: ");
Serial.println(pCharacteristic->getValue().c_str());
};
void onWrite(NimBLECharacteristic *pCharacteristic)
{
Serial.print(pCharacteristic->getUUID().toString().c_str());
Serial.print(": onWrite(), value: ");
Serial.println(pCharacteristic->getValue().c_str());
};
/** Called before notification or indication is sent,
* the value can be changed here before sending if desired.
*/
void onNotify(NimBLECharacteristic *pCharacteristic)
{
Serial.println("Sending notification to clients");
};
/** The status returned in status is defined in NimBLECharacteristic.h.
* The value returned in code is the NimBLE host return code.
*/
void onStatus(NimBLECharacteristic *pCharacteristic, Status status, int code)
{
String str = ("Notification/Indication status code: ");
str += status;
str += ", return code: ";
str += code;
str += ", ";
str += NimBLEUtils::returnCodeToString(code);
Serial.println(str);
};
void onSubscribe(NimBLECharacteristic *pCharacteristic, ble_gap_conn_desc *desc, uint16_t subValue)
{
String str = "Client ID: ";
str += desc->conn_handle;
str += " Address: ";
str += std::string(NimBLEAddress(desc->peer_ota_addr)).c_str();
if (subValue == 0)
{
str += " Unsubscribed to ";
}
else if (subValue == 1)
{
str += " Subscribed to notifications for ";
}
else if (subValue == 2)
{
str += " Subscribed to indications for ";
}
else if (subValue == 3)
{
str += " Subscribed to notifications and indications for ";
}
str += std::string(pCharacteristic->getUUID()).c_str();
Serial.println(str);
};
};
/** Handler class for descriptor actions */
class DescriptorCallbacks : public NimBLEDescriptorCallbacks
{
void onWrite(NimBLEDescriptor *pDescriptor)
{
std::string dscVal((char *)pDescriptor->getValue(), pDescriptor->getLength());
Serial.print("Descriptor witten value:");
Serial.println(dscVal.c_str());
};
void onRead(NimBLEDescriptor *pDescriptor)
{
Serial.print(pDescriptor->getUUID().toString().c_str());
Serial.println(" Descriptor read");
};
};
/*
* Client Stuff
*/
// This callback is for when data is received from Server
static void notifyCallback(
BLERemoteCharacteristic *pBLERemoteCharacteristic,
uint8_t *pData,
size_t length,
bool isNotify)
{
powerInstantaneous = pData[8] | pData[9] << 8; // 2 bytes of power
cadenceInstantaneous = 60; //(pData[4] | pData[5] << 8) / 2; // 2 bytes of power in 0.5 resolution RPM, convert to RPM
resistance = pData[6]; // 1 byte of resistance
Serial.printf("Power = %d | Cadence = %d | Resistance = %d\n", powerInstantaneous, cadenceInstantaneous, resistance);
}
/** None of these are required as they will be handled by the library with defaults. **
** Remove as you see fit for your needs */
class MyClientCallback : public BLEClientCallbacks
{
void onConnect(BLEClient *pclient)
{
}
void onDisconnect(BLEClient *pclient)
{
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer()
{
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient *pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr)
{
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr)
{
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our characteristic");
// Read the value of the characteristic.
if (pRemoteCharacteristic->canRead())
{
std::string value = pRemoteCharacteristic->readValue();
Serial.print("The characteristic value was: ");
Serial.println(value.c_str());
}
if (pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(notifyCallback);
connected = true;
return true;
}
/**
* Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
/**
* Called for each advertising BLE server.
*/
/*** Only a reference to the advertised device is passed now
void onResult(BLEAdvertisedDevice advertisedDevice) { **/
void onResult(BLEAdvertisedDevice *advertisedDevice)
{
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice->toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
/********************************************************************************
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
********************************************************************************/
if (advertisedDevice->haveServiceUUID() && advertisedDevice->isAdvertisingService(serviceUUID))
{
BLEDevice::getScan()->stop();
/*******************************************************************
myDevice = new BLEAdvertisedDevice(advertisedDevice);
*******************************************************************/
myDevice = advertisedDevice; /** Just save the reference now, no need to copy the object */
doConnect = true;
doScan = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
//delays for X ms, should not block execution
void softDelay(unsigned long delayTime)
{
unsigned long startTime = millis();
while ((millis() - startTime) < delayTime)
{
//wait
}
}
/** Define callback instances globally to use for multiple Characteristics \ Descriptors */
// This section is for the Server that will broadcast the data as Cycling Power
static DescriptorCallbacks dscCallbacks;
static CharacteristicCallbacks chrCallbacks;
NimBLECharacteristic *CyclingPowerFeature = NULL;
NimBLECharacteristic *CyclingPowerMeasurement = NULL;
NimBLECharacteristic *CyclingPowerSensorLocation = NULL;
NimBLECharacteristic *HRMeasurement = NULL;
unsigned char bleBuffer[8];
unsigned char slBuffer[1];
unsigned char fBuffer[4];
unsigned short revolutions = 0;
unsigned short timestamp = 0;
unsigned short flags = 0x20;
byte sensorlocation = 0x0D;
long lastNotify = 0;
long lastRevolution = 0;
void setup()
{
Serial.begin(115200);
Serial.println("Starting NimBLE Server");
/** sets device name */
NimBLEDevice::init("QZESP");
/** Optional: set the transmit power, default is 3db */
NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
fBuffer[0] = 0x00;
fBuffer[1] = 0x00;
fBuffer[2] = 0x00;
fBuffer[3] = 0x08;
slBuffer[0] = sensorlocation & 0xff;
NimBLEService *pDeadService = pServer->createService("1818");
CyclingPowerFeature = pDeadService->createCharacteristic(
"2A65",
NIMBLE_PROPERTY::READ);
CyclingPowerSensorLocation = pDeadService->createCharacteristic(
"2A5D",
NIMBLE_PROPERTY::READ);
CyclingPowerMeasurement = pDeadService->createCharacteristic(
"2A63",
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
CyclingPowerFeature->setValue(fBuffer, 4);
CyclingPowerSensorLocation->setValue(slBuffer, 1);
CyclingPowerMeasurement->setValue(slBuffer, 1);
/** Start the services when finished creating all Characteristics and Descriptors */
pDeadService->start();
#if 0
// HR service
NimBLEService *pHRService = pServer->createService("180D");
HRMeasurement = pHRService->createCharacteristic(
"2A37",
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
HRMeasurement->setValue(fBuffer, 2);
/** Start the services when finished creating all Characteristics and Descriptors */
pHRService->start();
#endif
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
/** Add the services to the advertisement data **/
// pAdvertising->addServiceUUID(pHRService->getUUID());
pAdvertising->addServiceUUID(pDeadService->getUUID());
pAdvertising->setScanResponse(true);
pAdvertising->start();
Serial.println("Advertising Started");
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan *pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
}
void loop()
{
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true)
{
if (connectToServer())
{
Serial.println("We are now connected to the BLE Server.");
}
else
{
Serial.println("We have failed to connect to the server; there is nothing more we will do.");
}
doConnect = false;
}
// If we are connected to a peer BLE Server, update the characteristic each time we are reached
// with the current time since boot.
if (connected)
{
//Stuff to do when connected to Client
}
else if (doScan)
{
BLEDevice::getScan()->start(0); // this is just sample to start scan after disconnect, most likely there is better way to do it in arduino
}
// convert RPM to timestamp
if (cadenceInstantaneous != 0 && (millis()) >= (lastRevolution + (60000 / cadenceInstantaneous)))
{
revolutions++; // One crank revolution should have passed, add one revolution
timestamp = (unsigned short)(((millis() * 1024) / 1000) % 65536); // create timestamp and format
lastRevolution = millis();
}
if (millis() - lastNotify >= 1000) // do this every second
{
//if (pServer->getConnectedCount() > 0)
{
bleBuffer[0] = flags & 0xff;
bleBuffer[1] = (flags >> 8) & 0xff;
bleBuffer[2] = powerInstantaneous & 0xff;
bleBuffer[3] = (powerInstantaneous >> 8) & 0xff;
bleBuffer[4] = revolutions & 0xff;
bleBuffer[5] = (revolutions >> 8) & 0xff;
bleBuffer[6] = timestamp & 0xff;
bleBuffer[7] = (timestamp >> 8) & 0xff;
CyclingPowerMeasurement->setValue(bleBuffer, 8);
CyclingPowerMeasurement->notify();
/*bleBuffer[0] = 0;
bleBuffer[1] = powerInstantaneous;
HRMeasurement->setValue(bleBuffer, 2);
HRMeasurement->notify();*/
lastNotify = millis();
}
}
/*if (pServer->getConnectedCount() == 0)
{
powerInstantaneous = 0;
}*/
}

View File

@@ -1,53 +0,0 @@
#include <NimBLEDevice.h>
#define INDOOR_BIKE_DATA_UUID "00002AD2-0000-1000-8000-00805f9b34fb"
#define CUSTOM_SERVICE_UUID "ce060000-43e5-11e4-916c-0800200c9a66"
NimBLEServer* pServer = nullptr;
NimBLECharacteristic* pIndoorBikeDataChar = nullptr;
class ServerCallbacks: public NimBLEServerCallbacks {
void onConnect(NimBLEServer* pServer) {
Serial.println("Client connected");
};
void onDisconnect(NimBLEServer* pServer) {
Serial.println("Client disconnected");
}
};
void setup() {
Serial.begin(115200);
Serial.println("Starting NimBLE Server");
NimBLEDevice::init("PM5 431431183 Row");
pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());
NimBLEService* pFtmService = pServer->createService("1826");
//NimBLEService* pCustomService = pServer->createService(CUSTOM_SERVICE_UUID);
pIndoorBikeDataChar = pFtmService->createCharacteristic(
INDOOR_BIKE_DATA_UUID,
NIMBLE_PROPERTY::READ |
NIMBLE_PROPERTY::NOTIFY
);
pFtmService->start();
//pCustomService->start();
NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID(pFtmService->getUUID());
//pAdvertising->addServiceUUID(CUSTOM_SERVICE_UUID);
const std::string data = { 0x01, 0x10, 0x00 }; // Imposta i valori desiderati
pAdvertising->setServiceData(pFtmService->getUUID(), data);
pAdvertising->start();
Serial.println("Advertising started");
}
void loop() {
// Metti qui il tuo codice principale, da eseguire ripetutamente
// Ad esempio, potresti aggiornare il valore della caratteristica Indoor Bike Data
}

133
README.md
View File

@@ -1,131 +1,62 @@
# 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>
<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|
|BitGym Compatibility|X|X|X|X||
# 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||
|Zwift Play & Click support|X|||||
|MQTT integration|X|X|X|X||
|OpenSoundControl integration|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.
Read the [installation procedure](docs/10_Installation.md)
You can install on multiple platforms.
Read the [installation procedure](docs/10_Installation.md)
### Tested on
The QDomyos-Zwift application can run on [Macintosh or Linux devices](docs/10_Installation.md) iOS, and Android.
It supports any [FTMS-compatible application](docs/20_supported_devices_and_applications.md) software and most [bluetooth enabled device](docs/20_supported_devices_and_applications.md).
You can run the app on [Macintosh or Linux devices](docs/10_Installation.md). IOS and Android are also supported.
### No GUI version
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
run as
$ sudo ./qdomyos-zwift -no-gui
$ sudo ./qdomyos-zwift -no-gui
### Reference
=> GitHub Repository: [QDomyos-Zwift on GitHub](https://github.com/ProH4Ck/treadmill-bridge)
https://github.com/ProH4Ck/treadmill-bridge
=> Treadmill Incline Reference: [What Is 10 Degrees in Incline on a Treadmill?](https://www.livestrong.com/article/422012-what-is-10-degrees-in-incline-on-a-treadmill/)
https://www.livestrong.com/article/422012-what-is-10-degrees-in-incline-on-a-treadmill/
=> Icon Attribution: Icons used in this documentation are from [Flaticon.com](https://www.flaticon.com)
Icons used in this documentation comes from [flaticon.com](https://www.flaticon.com)
### Blog
=> Related Blog: [Roberto Viola's Blog](https://robertoviola.cloud)
https://robertoviola.cloud

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

@@ -53,17 +53,12 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_accessibility_support_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bluetooth.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bluetooth_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bodymovin_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bootstrap_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_charts.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_charts_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_clipboard_support_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_concurrent.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_concurrent_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_core.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_core_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_datavisualization.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_datavisualization_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_devicediscovery_support_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_edid_support_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_eventdispatcher_support_private.pri \
@@ -76,9 +71,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_gui_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_help.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_help_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_httpserver.pri \
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_httpserver_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_httpserver.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_location.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_location_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_macextras.pri \
@@ -103,8 +95,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioning_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioningquick.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioningquick_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_purchasing.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_purchasing_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qml.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qml_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qmldebug_private.pri \
@@ -117,16 +107,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qmlworkerscript_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qtmultimediaquicktools_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3d.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3d_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dassetimport.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dassetimport_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3drender.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3drender_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3druntimerender.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3druntimerender_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dutils.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dutils_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quickcontrols2.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quickcontrols2_private.pri \
@@ -140,21 +120,12 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_remoteobjects_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_repparser.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_repparser_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_script.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_script_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scripttools.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scripttools_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scxml.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scxml_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sensors.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sensors_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_serialbus.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_serialbus_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sql.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sql_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_sslserver.pri \
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_sslserver_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sslserver.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_svg.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_svg_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_testlib.pri \
@@ -165,8 +136,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uiplugin.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uitools.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uitools_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_virtualkeyboard.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_virtualkeyboard_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_webchannel.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_webchannel_private.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_websockets.pri \
@@ -225,26 +194,15 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtiff.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtmedia_audioengine.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtmultimedia_m3u.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtpassthrucanbus.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtpeakcanbus.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtposition_cl.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtposition_positionpoll.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensorgestures_plugin.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensorgestures_shakeplugin.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensors_generic.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensors_ios.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qttinycanbus.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtuiotouchplugin.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualcanbus.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_hangul.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_openwnn.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_pinyin.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_tcime.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_thai.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboardplugin.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtwebview_darwin.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwbmp.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwebgl.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwebp.pri \
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_scene2d.pri \
../../Qt/5.15.2/ios/mkspecs/features/qt_functions.prf \
@@ -261,9 +219,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/features/default_pre.prf \
../../Qt/5.15.2/ios/mkspecs/features/mac/default_pre.prf \
../../Qt/5.15.2/ios/mkspecs/features/uikit/default_pre.prf \
../defaults.pri \
../src/purchasing/purchasing.pri \
../src/qdomyos-zwift.pri \
../../Qt/5.15.2/ios/mkspecs/features/resolve_config.prf \
../../Qt/5.15.2/ios/mkspecs/features/uikit/resolve_config.prf \
../../Qt/5.15.2/ios/mkspecs/features/default_post.prf \
@@ -271,9 +226,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/features/uikit/default_post.prf \
../../Qt/5.15.2/ios/mkspecs/macx-ios-clang/features/default_post.prf \
../../Qt/5.15.2/ios/mkspecs/features/mac/objective_c.prf \
../../Qt/5.15.2/ios/mkspecs/features/qmltypes.prf \
../../Qt/5.15.2/ios/mkspecs/features/metatypes.prf \
../../Qt/5.15.2/ios/mkspecs/features/ltcg.prf \
../../Qt/5.15.2/ios/mkspecs/features/qml_debug.prf \
../../Qt/5.15.2/ios/mkspecs/features/mac/mac.prf \
../../Qt/5.15.2/ios/mkspecs/features/uikit/bitcode.prf \
@@ -312,18 +264,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/lib/libqtharfbuzz_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Core_debug.prl \
../../Qt/5.15.2/ios/lib/libqtpcre2_debug.prl \
../../Qt/5.15.2/ios/plugins/mediaservice/libqavfmediaplayer_debug.prl \
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_esri_debug.prl \
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_itemsoverlay_debug.prl \
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_mapbox_debug.prl \
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_mapboxgl_debug.prl \
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_nokia_debug.prl \
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_osm_debug.prl \
../../Qt/5.15.2/ios/plugins/webview/libqtwebview_darwin_debug.prl \
../../Qt/5.15.2/ios/plugins/mediaservice/libqavfcamera_debug.prl \
../../Qt/5.15.2/ios/plugins/mediaservice/libqtmedia_audioengine_debug.prl \
../../Qt/5.15.2/ios/plugins/audio/libqtaudio_coreaudio_debug.prl \
../../Qt/5.15.2/ios/plugins/playlistformats/libqtmultimedia_m3u_debug.prl \
../../Qt/5.15.2/ios/plugins/imageformats/libqgif_debug.prl \
../../Qt/5.15.2/ios/plugins/imageformats/libqicns_debug.prl \
../../Qt/5.15.2/ios/plugins/imageformats/libqico_debug.prl \
@@ -348,51 +288,32 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/plugins/qmltooling/libqmldbg_server_debug.prl \
../../Qt/5.15.2/ios/plugins/qmltooling/libqmldbg_tcp_debug.prl \
../../Qt/5.15.2/ios/plugins/bearer/libqgenericbearer_debug.prl \
../../Qt/5.15.2/ios/plugins/texttospeech/libqtexttospeech_speechios_debug.prl \
../../Qt/5.15.2/ios/plugins/sqldrivers/libqsqlite_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5HttpServer_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5SslServer_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Charts_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Widgets_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Location_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5PositioningQuick_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5QuickControls2_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Quick_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Multimedia_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5WebView_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Bluetooth_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Xml_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Positioning_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5QmlModels_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Qml_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5NetworkAuth_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5WebSockets_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Network_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5TextToSpeech_debug.prl \
../../Qt/5.15.2/ios/lib/libQt5Concurrent_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick.2/libqtquick2plugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Layouts/libqquicklayoutsplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/libqtquickcontrols2plugin_debug.prl \
../../Qt/5.15.2/ios/qml/Qt/labs/settings/libqmlsettingsplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Material/libqtquickcontrols2materialstyleplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/libqtgraphicaleffectsplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Window.2/libwindowplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQml/libqmlplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Templates.2/libqtquicktemplates2plugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/private/libqtgraphicaleffectsprivate_debug.prl \
../../Qt/5.15.2/ios/qml/QtQml/Models.2/libmodelsplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQml/WorkerScript.2/libworkerscriptplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Window.2/libwindowplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Material/libqtquickcontrols2materialstyleplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtWebView/libdeclarative_webview_debug.prl \
../../Qt/5.15.2/ios/qml/QtCharts/libqtchartsqml2_debug.prl \
../../Qt/5.15.2/ios/qml/Qt/labs/folderlistmodel/libqmlfolderlistmodelplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/libdialogplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtPositioning/libdeclarative_positioning_debug.prl \
../../Qt/5.15.2/ios/qml/QtLocation/libdeclarative_location_debug.prl \
../../Qt/5.15.2/ios/qml/Qt/labs/folderlistmodel/libqmlfolderlistmodelplugin_debug.prl \
../../Qt/5.15.2/ios/qml/Qt/labs/settings/libqmlsettingsplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/Private/libdialogsprivateplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Controls/libqtquickcontrolsplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/PrivateWidgets/libwidgetsplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/libqtgraphicaleffectsplugin_debug.prl \
../../Qt/5.15.2/ios/qml/Qt/labs/platform/libqtlabsplatformplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtMultimedia/libdeclarative_multimedia_debug.prl \
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/private/libqtgraphicaleffectsprivate_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Layouts/libqquicklayoutsplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Fusion/libqtquickcontrols2fusionstyleplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Universal/libqtquickcontrols2universalstyleplugin_debug.prl \
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Imagine/libqtquickcontrols2imaginestyleplugin_debug.prl
@@ -440,17 +361,12 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_accessibility_support_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bluetooth.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bluetooth_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bodymovin_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bootstrap_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_charts.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_charts_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_clipboard_support_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_concurrent.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_concurrent_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_core.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_core_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_datavisualization.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_datavisualization_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_devicediscovery_support_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_edid_support_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_eventdispatcher_support_private.pri:
@@ -463,9 +379,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_gui_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_help.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_help_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_httpserver.pri:
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_httpserver_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_httpserver.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_location.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_location_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_macextras.pri:
@@ -490,8 +403,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioning_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioningquick.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioningquick_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_purchasing.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_purchasing_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qml.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qml_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qmldebug_private.pri:
@@ -504,16 +415,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qmlworkerscript_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qtmultimediaquicktools_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3d.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3d_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dassetimport.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dassetimport_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3drender.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3drender_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3druntimerender.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3druntimerender_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dutils.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dutils_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quickcontrols2.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quickcontrols2_private.pri:
@@ -527,21 +428,12 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_remoteobjects_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_repparser.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_repparser_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_script.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_script_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scripttools.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scripttools_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scxml.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scxml_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sensors.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sensors_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_serialbus.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_serialbus_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sql.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sql_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_sslserver.pri:
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_sslserver_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sslserver.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_svg.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_svg_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_testlib.pri:
@@ -552,8 +444,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uiplugin.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uitools.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uitools_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_virtualkeyboard.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_virtualkeyboard_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_webchannel.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_webchannel_private.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_websockets.pri:
@@ -612,26 +502,15 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtiff.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtmedia_audioengine.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtmultimedia_m3u.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtpassthrucanbus.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtpeakcanbus.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtposition_cl.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtposition_positionpoll.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensorgestures_plugin.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensorgestures_shakeplugin.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensors_generic.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensors_ios.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qttinycanbus.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtuiotouchplugin.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualcanbus.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_hangul.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_openwnn.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_pinyin.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_tcime.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_thai.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboardplugin.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtwebview_darwin.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwbmp.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwebgl.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwebp.pri:
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_scene2d.pri:
../../Qt/5.15.2/ios/mkspecs/features/qt_functions.prf:
@@ -648,9 +527,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/features/default_pre.prf:
../../Qt/5.15.2/ios/mkspecs/features/mac/default_pre.prf:
../../Qt/5.15.2/ios/mkspecs/features/uikit/default_pre.prf:
../defaults.pri:
../src/purchasing/purchasing.pri:
../src/qdomyos-zwift.pri:
../../Qt/5.15.2/ios/mkspecs/features/resolve_config.prf:
../../Qt/5.15.2/ios/mkspecs/features/uikit/resolve_config.prf:
../../Qt/5.15.2/ios/mkspecs/features/default_post.prf:
@@ -658,9 +534,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/mkspecs/features/uikit/default_post.prf:
../../Qt/5.15.2/ios/mkspecs/macx-ios-clang/features/default_post.prf:
../../Qt/5.15.2/ios/mkspecs/features/mac/objective_c.prf:
../../Qt/5.15.2/ios/mkspecs/features/qmltypes.prf:
../../Qt/5.15.2/ios/mkspecs/features/metatypes.prf:
../../Qt/5.15.2/ios/mkspecs/features/ltcg.prf:
../../Qt/5.15.2/ios/mkspecs/features/qml_debug.prf:
../../Qt/5.15.2/ios/mkspecs/features/mac/mac.prf:
../../Qt/5.15.2/ios/mkspecs/features/uikit/bitcode.prf:
@@ -699,18 +572,6 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/lib/libqtharfbuzz_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Core_debug.prl:
../../Qt/5.15.2/ios/lib/libqtpcre2_debug.prl:
../../Qt/5.15.2/ios/plugins/mediaservice/libqavfmediaplayer_debug.prl:
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_esri_debug.prl:
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_itemsoverlay_debug.prl:
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_mapbox_debug.prl:
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_mapboxgl_debug.prl:
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_nokia_debug.prl:
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_osm_debug.prl:
../../Qt/5.15.2/ios/plugins/webview/libqtwebview_darwin_debug.prl:
../../Qt/5.15.2/ios/plugins/mediaservice/libqavfcamera_debug.prl:
../../Qt/5.15.2/ios/plugins/mediaservice/libqtmedia_audioengine_debug.prl:
../../Qt/5.15.2/ios/plugins/audio/libqtaudio_coreaudio_debug.prl:
../../Qt/5.15.2/ios/plugins/playlistformats/libqtmultimedia_m3u_debug.prl:
../../Qt/5.15.2/ios/plugins/imageformats/libqgif_debug.prl:
../../Qt/5.15.2/ios/plugins/imageformats/libqicns_debug.prl:
../../Qt/5.15.2/ios/plugins/imageformats/libqico_debug.prl:
@@ -735,51 +596,32 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
../../Qt/5.15.2/ios/plugins/qmltooling/libqmldbg_server_debug.prl:
../../Qt/5.15.2/ios/plugins/qmltooling/libqmldbg_tcp_debug.prl:
../../Qt/5.15.2/ios/plugins/bearer/libqgenericbearer_debug.prl:
../../Qt/5.15.2/ios/plugins/texttospeech/libqtexttospeech_speechios_debug.prl:
../../Qt/5.15.2/ios/plugins/sqldrivers/libqsqlite_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5HttpServer_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5SslServer_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Charts_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Widgets_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Location_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5PositioningQuick_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5QuickControls2_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Quick_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Multimedia_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5WebView_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Bluetooth_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Xml_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Positioning_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5QmlModels_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Qml_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5NetworkAuth_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5WebSockets_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Network_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5TextToSpeech_debug.prl:
../../Qt/5.15.2/ios/lib/libQt5Concurrent_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick.2/libqtquick2plugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Layouts/libqquicklayoutsplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/libqtquickcontrols2plugin_debug.prl:
../../Qt/5.15.2/ios/qml/Qt/labs/settings/libqmlsettingsplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Material/libqtquickcontrols2materialstyleplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/libqtgraphicaleffectsplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Window.2/libwindowplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQml/libqmlplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Templates.2/libqtquicktemplates2plugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/private/libqtgraphicaleffectsprivate_debug.prl:
../../Qt/5.15.2/ios/qml/QtQml/Models.2/libmodelsplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQml/WorkerScript.2/libworkerscriptplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Window.2/libwindowplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Material/libqtquickcontrols2materialstyleplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtWebView/libdeclarative_webview_debug.prl:
../../Qt/5.15.2/ios/qml/QtCharts/libqtchartsqml2_debug.prl:
../../Qt/5.15.2/ios/qml/Qt/labs/folderlistmodel/libqmlfolderlistmodelplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/libdialogplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtPositioning/libdeclarative_positioning_debug.prl:
../../Qt/5.15.2/ios/qml/QtLocation/libdeclarative_location_debug.prl:
../../Qt/5.15.2/ios/qml/Qt/labs/folderlistmodel/libqmlfolderlistmodelplugin_debug.prl:
../../Qt/5.15.2/ios/qml/Qt/labs/settings/libqmlsettingsplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/Private/libdialogsprivateplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Controls/libqtquickcontrolsplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/PrivateWidgets/libwidgetsplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/libqtgraphicaleffectsplugin_debug.prl:
../../Qt/5.15.2/ios/qml/Qt/labs/platform/libqtlabsplatformplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtMultimedia/libdeclarative_multimedia_debug.prl:
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/private/libqtgraphicaleffectsprivate_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Layouts/libqquicklayoutsplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Fusion/libqtquickcontrols2fusionstyleplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Universal/libqtquickcontrols2universalstyleplugin_debug.prl:
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Imagine/libqtquickcontrols2imaginestyleplugin_debug.prl:

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,14 +80,7 @@
BlueprintName = "watchkit"
ReferencedContainer = "container:qdomyoszwift.xcodeproj">
</BuildableReference>
</RemoteRunnable>
<MacroExpansion>
<BuildableReference
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,56 +8,26 @@
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!
@IBOutlet weak var cmbSports: WKInterfacePicker!
static var start: Bool! = false
let pedometer = CMPedometer()
var sport: Int = 0
override func awake(withContext context: Any?) {
super.awake(withContext: context)
let sports: [WKPickerItem] = [WKPickerItem(),WKPickerItem(),WKPickerItem(),WKPickerItem(),WKPickerItem()]
sports[0].title = "Bike"
sports[1].title = "Run"
sports[2].title = "Walk"
sports[3].title = "Elliptical"
sports[4].title = "Rowing"
cmbSports.setItems(sports)
sport = UserDefaults.standard.value(forKey: "sport") as? Int ?? 0
cmbSports.setSelectedItemIndex(sport)
// Configure interface objects here.
print("AWAKE")
}
@IBAction func changeSport(_ value: Int) {
self.sport = value
UserDefaults.standard.set(value, forKey: "sport")
UserDefaults.standard.synchronize()
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
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() {
@@ -74,7 +44,6 @@ extension MainController {
MainController.start = true
startButton.setTitle("Stop")
WorkoutTracking.authorizeHealthKit()
WorkoutTracking.shared.setSport(sport)
WorkoutTracking.shared.startWorkOut()
WorkoutTracking.shared.delegate = self
@@ -90,7 +59,6 @@ extension MainController {
}
extension MainController: WorkoutTrackingDelegate {
func didReceiveHealthKitDistanceCycling(_ distanceCycling: Double) {
}
@@ -104,25 +72,10 @@ 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
WorkoutTracking.steps = WatchKitConnection.steps
if Locale.current.measurementSystem != "Metric" {
self.distanceLabel.setText("Distance \(String(format:"%.2f", WorkoutTracking.distance))")
} else {
self.distanceLabel.setText("Distance \(String(format:"%.2f", WorkoutTracking.distance * 1.60934))")
}
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")
}
}
@@ -131,11 +84,3 @@ extension MainController: WatchKitConnectionDelegate {
userNameLabel.setText(userName)
}
}
extension Locale
{
var measurementSystem : String?
{
return (self as NSLocale).object(forKey: NSLocale.Key.measurementSystem) as? String
}
}

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>

View File

@@ -23,11 +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
public static var speed = 0.0
public static var cadence = 0.0
public static var power = 0.0
public static var steps = 0
weak var delegate: WatchKitConnectionDelegate?
private override init() {
@@ -70,17 +65,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
if let stepsDouble = result["steps"] as? Double {
let iSteps = Int(stepsDouble)
WatchKitConnection.steps = iSteps
}
}, errorHandler: { (error) in
print(error)
})

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,15 +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
public static var speed = Double()
public static var power = Double()
public static var steps = Int()
public static var cadence = Double()
public static var lastDateMetric = Date()
var sport: Int = 0
let healthStore = HKHealthStore()
let configuration = HKWorkoutConfiguration()
var workoutSession: HKWorkoutSession!
@@ -89,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")
}
@@ -107,23 +91,8 @@ extension WorkoutTracking {
}
}
func setSport(_ sport: Int) {
self.sport = sport
}
private func configWorkout() {
var activityType = HKWorkoutActivityType.cycling
if self.sport == 1 {
activityType = HKWorkoutActivityType.running
} else if self.sport == 2 {
activityType = HKWorkoutActivityType.walking
} else if self.sport == 3 {
activityType = HKWorkoutActivityType.elliptical
} else if self.sport == 4 {
activityType = HKWorkoutActivityType.rowing
}
configuration.activityType = activityType
configuration.activityType = .cycling
configuration.locationType = .indoor
do {
@@ -151,37 +120,13 @@ 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: .activeEnergyBurned)!,
HKSampleType.workoutType()
])
HKHealthStore().requestAuthorization(toShare: infoToShare, read: infoToRead) { (success, error) in
if success {
@@ -196,7 +141,6 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
}
func startWorkOut() {
WorkoutTracking.lastDateMetric = Date()
print("Start workout")
configWorkout()
workoutSession.startActivity(with: Date())
@@ -205,10 +149,6 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
if let error = error {
print(error)
}
if self.sport > 0 {
self.workoutBuilder.dataSource?.enableCollection(for: HKQuantityType.quantityType(forIdentifier: .distanceWalkingRunning)!, predicate: nil)
}
}
}
@@ -233,109 +173,28 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
end: Date())
workoutBuilder.add([sample]) {(success, error) in}
guard let quantityTypeDistance = HKQuantityType.quantityType(
forIdentifier: .distanceCycling) else {
return
}
let unitDistance = HKUnit.mile()
let miles = WorkoutTracking.distance
let quantityMiles = HKQuantity(unit: unitDistance,
doubleValue: miles)
if(sport == 0) {
guard let quantityTypeDistance = HKQuantityType.quantityType(
forIdentifier: .distanceCycling) else {
return
}
let sampleDistance = HKCumulativeQuantitySeriesSample(type: quantityTypeDistance,
quantity: quantityMiles,
start: workoutSession.startDate!,
end: Date())
workoutBuilder.add([sampleDistance]) {(success, error) in
if let error = error {
print(error)
}
self.workoutBuilder.endCollection(withEnd: Date()) { (success, error) in
if let error = error {
print(error)
}
self.workoutBuilder.finishWorkout{ (workout, error) in
if let error = error {
print(error)
}
workout?.setValue(quantityMiles, forKey: "totalDistance")
}
}
}
} else {
// Guard to check if steps quantity type is available
guard let quantityTypeSteps = HKQuantityType.quantityType(
forIdentifier: .stepCount) else {
return
}
let stepsQuantity = HKQuantity(unit: HKUnit.count(), doubleValue: Double(WorkoutTracking.steps))
// Create a sample for total steps
let sampleSteps = HKCumulativeQuantitySeriesSample(
type: quantityTypeSteps,
quantity: stepsQuantity, // Use your steps quantity here
start: workoutSession.startDate!,
end: Date())
// Add the steps sample to workout builder
workoutBuilder.add([sampleSteps]) { (success, error) in
if let error = error {
print(error)
}
// End the data collection
self.workoutBuilder.endCollection(withEnd: Date()) { (success, error) in
if let error = error {
print(error)
}
// Finish the workout and save total steps
self.workoutBuilder.finishWorkout { (workout, error) in
if let error = error {
print(error)
}
workout?.setValue(stepsQuantity, forKey: "totalSteps")
}
}
}
guard let quantityTypeDistance = HKQuantityType.quantityType(
forIdentifier: .distanceWalkingRunning) else {
return
}
let sampleDistance = HKCumulativeQuantitySeriesSample(type: quantityTypeDistance,
quantity: quantityMiles,
start: workoutSession.startDate!,
end: Date())
workoutBuilder.add([sampleDistance]) {(success, error) in
if let error = error {
print(error)
}
self.workoutBuilder.endCollection(withEnd: Date()) { (success, error) in
if let error = error {
print(error)
}
self.workoutBuilder.finishWorkout{ (workout, error) in
if let error = error {
print(error)
}
workout?.setValue(quantityMiles, forKey: "totalDistance")
}
}
}
}
let sampleDistance = HKCumulativeQuantitySeriesSample(type: quantityTypeDistance,
quantity: quantityMiles,
start: workoutSession.startDate!,
end: Date())
workoutBuilder.add([sample]) {(success, error) in}
workoutBuilder.add([sampleDistance]) {(success, error) in}
workoutBuilder.endCollection(withEnd: Date()) { (success, error) in
}
}
func fetchStepCounts() {
@@ -378,135 +237,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

@@ -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="20037" 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="20020"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="20006"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="17500"/>
</dependencies>
<scenes>
<!--Main-->
@@ -12,26 +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"/>
<picker height="100" alignment="left" id="OTR-HF-vYb">
<connections>
<action selector="changeSport:" destination="Tpn-rd-UUX" id="3vY-lq-IhZ"/>
</connections>
</picker>
</items>
<connections>
<outlet property="caloriesLabel" destination="Szi-Jp-J3S" id="trd-YS-bJy"/>
<outlet property="cmbSports" destination="OTR-HF-vYb" id="Ws5-w9-ZT8"/>
<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,15 +0,0 @@
QT += gui bluetooth widgets xml positioning quick networkauth websockets texttospeech location multimedia
QTPLUGIN += qavfmediaplayer
QT+= charts
unix:android: QT += androidextras gui-private
android: include(android_openssl/openssl.pri)
INCLUDEPATH += $$PWD/src/qmdnsengine/src/include
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/src/android
ANDROID_ABIS = armeabi-v7a arm64-v8a x86 x86_64
#QMAKE_CXXFLAGS += -Werror=suggest-override

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

@@ -1,96 +0,0 @@
# Define build image
FROM ubuntu:latest AS build
# Install essential build dependencies
ARG DEBIAN_FRONTEND=noninteractive
RUN apt update && apt upgrade -y \
&& apt install --no-install-recommends -y \
git \
ca-certificates \
qtquickcontrols2-5-dev \
qtconnectivity5-dev \
qtbase5-private-dev \
qtpositioning5-dev \
libqt5charts5-dev \
libqt5networkauth5-dev \
libqt5websockets5-dev \
qml-module* \
libqt5texttospeech5-dev \
qtlocation5-dev \
qtmultimedia5-dev \
g++ \
make \
wget \
unzip \
&& rm -rf /var/lib/apt/lists/*
# Define runtime image
FROM ubuntu:latest AS runtime
# Install essential runtime dependencies
ARG DEBIAN_FRONTEND=noninteractive
RUN apt update && apt upgrade -y \
&& apt install --no-install-recommends -y \
libqt5bluetooth5 \
libqt5widgets5 \
libqt5positioning5 \
libqt5xml5 \
libqt5charts5 \
qt5-assistant \
libqt5networkauth5 \
libqt5websockets5 \
qml-module* \
libqt5texttospeech5 \
libqt5location5-plugins \
libqt5multimediawidgets5 \
libqt5multimedia5-plugins \
libqt5multimedia5 \
qml-module-qtquick-controls2 \
libqt5location5 \
bluez \
dbus \
tigervnc-standalone-server \
tigervnc-tools \
libgl1-mesa-dri \
xfonts-base \
x11-xserver-utils \
tigervnc-common \
net-tools \
&& rm -rf /var/lib/apt/lists/*
# Stage 1: Build
FROM build AS builder
# Clone the project and build it
WORKDIR /usr/local/src
RUN git clone --recursive https://github.com/cagnulein/qdomyos-zwift.git
WORKDIR /usr/local/src/qdomyos-zwift
RUN git submodule update --init src/smtpclient/ \
&& git submodule update --init src/qmdnsengine/ \
&& git submodule update --init tst/googletest/
WORKDIR /usr/local/src/qdomyos-zwift/src
RUN qmake qdomyos-zwift.pro \
&& make -j4
# Stage 2: Runtime
FROM runtime
# Copy the built binary to /usr/local/bin
COPY --from=builder /usr/local/src/qdomyos-zwift/src/qdomyos-zwift /usr/local/bin/qdomyos-zwift
# VNC configuration
RUN mkdir -p ~/.vnc && \
echo "securepassword" | vncpasswd -f > ~/.vnc/passwd && \
chmod 600 ~/.vnc/passwd
# .Xauthority configuration
RUN touch /root/.Xauthority
ENV DISPLAY=:99
# Start VNC server with authentication
CMD vncserver :99 -depth 24 -localhost no -xstartup qdomyos-zwift && \
sleep infinity

View File

@@ -1,2 +0,0 @@
#!/bin/bash
docker build -t qdomyos-zwift-vnc .

View File

@@ -1,10 +0,0 @@
services:
qdomyos-zwift-vnc:
image: qdomyos-zwift-vnc
container_name: qdomyos-zwift-vnc
privileged: true # Required for Bluetooth functionality
network_mode: "host" # Used to access host Bluetooth and D-Bus
volumes:
- /dev:/dev # Forward host devices (for Bluetooth)
- /run/dbus:/run/dbus # Forward D-Bus for Bluetooth interaction
restart: "no" # Do not restart the container automatically

View File

@@ -1,95 +0,0 @@
# Define build image
FROM ubuntu:latest AS build
# Install essential build dependencies
ARG DEBIAN_FRONTEND=noninteractive
RUN apt update && apt upgrade -y \
&& apt install --no-install-recommends -y \
git \
ca-certificates \
qtquickcontrols2-5-dev \
qtconnectivity5-dev \
qtbase5-private-dev \
qtpositioning5-dev \
libqt5charts5-dev \
libqt5networkauth5-dev \
libqt5websockets5-dev \
qml-module* \
libqt5texttospeech5-dev \
qtlocation5-dev \
qtmultimedia5-dev \
g++ \
make \
wget \
unzip \
&& rm -rf /var/lib/apt/lists/*
# Define runtime image
FROM ubuntu:latest AS runtime
# Install essential runtime dependencies
ARG DEBIAN_FRONTEND=noninteractive
RUN apt update && apt upgrade -y \
&& apt install --no-install-recommends -y \
libqt5bluetooth5 \
libqt5widgets5 \
libqt5positioning5 \
libqt5xml5 \
libqt5charts5 \
qt5-assistant \
libqt5networkauth5 \
libqt5websockets5 \
qml-module* \
libqt5texttospeech5 \
libqt5location5-plugins \
libqt5multimediawidgets5 \
libqt5multimedia5-plugins \
libqt5multimedia5 \
qml-module-qtquick-controls2 \
libqt5location5 \
bluez \
dbus \
&& rm -rf /var/lib/apt/lists/*
# Stage 1: Build
FROM build AS builder
# Define variables for Qt versions
ARG QT_VERSION=5.15
ARG QT_SUBVERSION=5.15.13
ARG QT_WEBPLUGIN_NAME=qtwebglplugin-everywhere-opensource-src
# Build WebGL plugin
WORKDIR /usr/local/src
RUN wget https://download.qt.io/official_releases/qt/${QT_VERSION}/${QT_SUBVERSION}/submodules/${QT_WEBPLUGIN_NAME}-${QT_SUBVERSION}.zip \
&& unzip ${QT_WEBPLUGIN_NAME}-${QT_SUBVERSION}.zip \
&& mv *-${QT_SUBVERSION} qtwebglplugin-everywhere \
&& cd qtwebglplugin-everywhere \
&& qmake \
&& make
# Clone the project and build it
WORKDIR /usr/local/src
RUN git clone --recursive https://github.com/cagnulein/qdomyos-zwift.git
WORKDIR /usr/local/src/qdomyos-zwift
RUN git submodule update --init src/smtpclient/ \
&& git submodule update --init src/qmdnsengine/ \
&& git submodule update --init tst/googletest/
WORKDIR /usr/local/src/qdomyos-zwift/src
RUN qmake qdomyos-zwift.pro \
&& make -j4
# Stage 2: Runtime
FROM runtime
# Copy the built binary to /usr/local/bin
COPY --from=builder /usr/local/src/qdomyos-zwift/src/qdomyos-zwift /usr/local/bin/qdomyos-zwift
# Copy WebGL plugin to the appropriate location
COPY --from=builder /usr/local/src/qtwebglplugin-everywhere/plugins/platforms/libqwebgl.so /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqwebgl.so
# Set the default command to run the application with WebGL
CMD ["qdomyos-zwift", "-qml", "-platform", "webgl:port=8080"]

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